/**
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <codecvt>
#include <iomanip>
#include <iostream>
#include <string>

#include "include/stack_walker.h"
#include "plugins/ecmascript/runtime/accessor_data.h"
#include "plugins/ecmascript/runtime/class_info_extractor.h"
#include "plugins/ecmascript/runtime/class_linker/program_object-inl.h"
#include "plugins/ecmascript/runtime/ecma_module.h"
#include "plugins/ecmascript/runtime/ecma_vm.h"
#include "plugins/ecmascript/runtime/global_dictionary-inl.h"
#include "plugins/ecmascript/runtime/global_env.h"
#include "plugins/ecmascript/runtime/ic/ic_handler.h"
#include "plugins/ecmascript/runtime/ic/property_box.h"
#include "plugins/ecmascript/runtime/ic/proto_change_details.h"
#include "plugins/ecmascript/runtime/jobs/micro_job_queue.h"
#include "plugins/ecmascript/runtime/jobs/pending_job.h"
#include "plugins/ecmascript/runtime/js_array.h"
#include "plugins/ecmascript/runtime/js_array_iterator.h"
#include "plugins/ecmascript/runtime/js_arraybuffer.h"
#include "plugins/ecmascript/runtime/js_arraylist.h"
#include "plugins/ecmascript/runtime/js_async_from_sync_iterator_object.h"
#include "plugins/ecmascript/runtime/js_async_function.h"
#include "plugins/ecmascript/runtime/js_async_generator_object.h"
#include "plugins/ecmascript/runtime/js_collator.h"
#include "plugins/ecmascript/runtime/js_dataview.h"
#include "plugins/ecmascript/runtime/js_date.h"
#include "plugins/ecmascript/runtime/js_date_time_format.h"
#include "plugins/ecmascript/runtime/js_for_in_iterator.h"
#include "plugins/ecmascript/runtime/js_function.h"
#include "plugins/ecmascript/runtime/js_function_extra_info.h"
#include "plugins/ecmascript/runtime/js_generator_object.h"
#include "plugins/ecmascript/runtime/js_global_object.h"
#include "plugins/ecmascript/runtime/js_handle.h"
#include "plugins/ecmascript/runtime/js_intl.h"
#include "plugins/ecmascript/runtime/js_locale.h"
#include "plugins/ecmascript/runtime/js_map.h"
#include "plugins/ecmascript/runtime/js_map_iterator.h"
#include "plugins/ecmascript/runtime/js_number_format.h"
#include "plugins/ecmascript/runtime/js_object-inl.h"
#include "plugins/ecmascript/runtime/js_plural_rules.h"
#include "plugins/ecmascript/runtime/js_primitive_ref.h"
#include "plugins/ecmascript/runtime/js_promise.h"
#include "plugins/ecmascript/runtime/js_realm.h"
#include "plugins/ecmascript/runtime/js_regexp.h"
#include "plugins/ecmascript/runtime/js_relative_time_format.h"
#include "plugins/ecmascript/runtime/js_set.h"
#include "plugins/ecmascript/runtime/js_set_iterator.h"
#include "plugins/ecmascript/runtime/js_regexp_iterator.h"
#include "plugins/ecmascript/runtime/js_string_iterator.h"
#include "plugins/ecmascript/runtime/js_tagged_number.h"
#include "plugins/ecmascript/runtime/js_tagged_value-inl.h"
#include "plugins/ecmascript/runtime/js_thread.h"
#include "plugins/ecmascript/runtime/js_typed_array.h"
#include "plugins/ecmascript/runtime/js_weak_container.h"
#include "plugins/ecmascript/runtime/layout_info-inl.h"
#include "plugins/ecmascript/runtime/lexical_env.h"
#include "plugins/ecmascript/runtime/linked_hash_table-inl.h"
#include "plugins/ecmascript/runtime/tagged_array.h"
#include "plugins/ecmascript/runtime/tagged_dictionary.h"
#include "plugins/ecmascript/runtime/template_map.h"
#include "plugins/ecmascript/runtime/transitions_dictionary.h"

namespace ark::ecmascript {
using MicroJobQueue = ark::ecmascript::job::MicroJobQueue;
using PendingJob = ark::ecmascript::job::PendingJob;

static constexpr uint32_t DUMP_TYPE_OFFSET = 12;
static constexpr uint32_t DUMP_PROPERTY_OFFSET = 20;

PandaString JSHClass::DumpJSType(JSType type)
{
    switch (type) {
        case JSType::HCLASS:
            return "JSHClass";
        case JSType::TAGGED_ARRAY:
            return "TaggedArray";
        case JSType::TAGGED_DICTIONARY:
            return "TaggedDictionary";
        case JSType::LINKED_HASH_SET:
            return "LinkedHashSet";
        case JSType::LINKED_HASH_MAP:
            return "LinkedHashMap";
        case JSType::STRING:
            return "BaseString";
        case JSType::JS_NATIVE_POINTER:
            return "NativePointer";
        case JSType::JS_OBJECT:
            return "Object";
        case JSType::JS_FUNCTION_BASE:
            return "Function Base";
        case JSType::JS_FUNCTION:
            return "Function";
        case JSType::JS_ERROR:
            return "Error";
        case JSType::JS_EVAL_ERROR:
            return "Eval Error";
        case JSType::JS_RANGE_ERROR:
            return "Range Error";
        case JSType::JS_TYPE_ERROR:
            return "Type Error";
        case JSType::JS_REFERENCE_ERROR:
            return "Reference Error";
        case JSType::JS_URI_ERROR:
            return "Uri Error";
        case JSType::JS_SYNTAX_ERROR:
            return "Syntax Error";
        case JSType::JS_REG_EXP:
            return "Regexp";
        case JSType::JS_SET:
            return "Set";
        case JSType::JS_MAP:
            return "Map";
        case JSType::JS_WEAK_SET:
            return "WeakSet";
        case JSType::JS_WEAK_MAP:
            return "WeakMap";
        case JSType::JS_DATE:
            return "Date";
        case JSType::JS_BOUND_FUNCTION:
            return "Bound Function";
        case JSType::JS_ARRAY:
            return "Array";
        case JSType::BIGINT:
            return "BigInt";
        case JSType::JS_TYPED_ARRAY:
            return "Typed Array";
        case JSType::JS_INT8_ARRAY:
            return "Int8 Array";
        case JSType::JS_UINT8_ARRAY:
            return "Uint8 Array";
        case JSType::JS_UINT8_CLAMPED_ARRAY:
            return "Uint8 Clamped Array";
        case JSType::JS_INT16_ARRAY:
            return "Int16 Array";
        case JSType::JS_UINT16_ARRAY:
            return "Uint16 Array";
        case JSType::JS_INT32_ARRAY:
            return "Int32 Array";
        case JSType::JS_UINT32_ARRAY:
            return "Uint32 Array";
        case JSType::JS_FLOAT32_ARRAY:
            return "Float32 Array";
        case JSType::JS_FLOAT64_ARRAY:
            return "Float64 Array";
        case JSType::JS_ARGUMENTS:
            return "Arguments";
        case JSType::JS_PROXY:
            return "Proxy";
        case JSType::JS_PRIMITIVE_REF:
            return "Primitive";
        case JSType::JS_DATA_VIEW:
            return "DataView";
        case JSType::JS_ITERATOR:
            return "Iterator";
        case JSType::JS_FORIN_ITERATOR:
            return "ForinInterator";
        case JSType::JS_MAP_ITERATOR:
            return "MapIterator";
        case JSType::JS_SET_ITERATOR:
            return "SetIterator";
        case JSType::JS_ARRAY_ITERATOR:
            return "ArrayIterator";
        case JSType::JS_STRING_ITERATOR:
            return "StringIterator";
        case JSType::JS_REG_EXP_ITERATOR:
            return "RegExpIterator";
        case JSType::JS_ARRAY_BUFFER:
            return "ArrayBuffer";
        case JSType::JS_PROXY_REVOC_FUNCTION:
            return "ProxyRevocFunction";
        case JSType::PROMISE_REACTIONS:
            return "PromiseReaction";
        case JSType::PROMISE_CAPABILITY:
            return "PromiseCapability";
        case JSType::PROMISE_ITERATOR_RECORD:
            return "PromiseIteratorRecord";
        case JSType::PROMISE_RECORD:
            return "PromiseRecord";
        case JSType::RESOLVING_FUNCTIONS_RECORD:
            return "ResolvingFunctionsRecord";
        case JSType::JS_PROMISE:
            return "Promise";
        case JSType::JS_PROMISE_REACTIONS_FUNCTION:
            return "PromiseReactionsFunction";
        case JSType::JS_PROMISE_EXECUTOR_FUNCTION:
            return "PromiseExecutorFunction";
        case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION:
            return "PromiseAllResolveElementFunction";
        case JSType::MICRO_JOB_QUEUE:
            return "MicroJobQueue";
        case JSType::PENDING_JOB:
            return "PendingJob";
        case JSType::COMPLETION_RECORD:
            return "CompletionRecord";
        case JSType::GLOBAL_ENV:
            return "GlobalEnv";
        case JSType::ACCESSOR_DATA:
            return "AccessorData";
        case JSType::INTERNAL_ACCESSOR:
            return "InternalAccessor";
        case JSType::SYMBOL:
            return "Symbol";
        case JSType::PROPERTY_BOX:
            return "PropertyBox";
        case JSType::JS_ASYNC_FUNCTION:
            return "AsyncFunction";
        case JSType::JS_ASYNC_GENERATOR_FUNCTION:
            return "AsyncGeneratorFunction";
        case JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION:
            return "AsyncAwaitStatusFunction";
        case JSType::JS_ASYNC_GENERATOR_RESOLVE_NEXT_FUNCTION:
            return "AsynGeneratorResolveNextFunction";
        case JSType::JS_ASYNC_FROM_SYNC_ITERATOR_VALUE_UNWRAP_FUNCTION:
            return "AsynFromSyncIteratorValueUnwrapFunction";
        case JSType::JS_ASYNC_FUNC_OBJECT:
            return "AsyncFunctionObject";
        case JSType::JS_REALM:
            return "Realm";
        case JSType::JS_GLOBAL_OBJECT:
            return "GlobalObject";
        case JSType::JS_INTL:
            return "JSIntl";
        case JSType::JS_LOCALE:
            return "JSLocale";
        case JSType::JS_DATE_TIME_FORMAT:
            return "JSDateTimeFormat";
        case JSType::JS_RELATIVE_TIME_FORMAT:
            return "JSRelativeTimeFormat";
        case JSType::JS_NUMBER_FORMAT:
            return "JSNumberFormat";
        case JSType::JS_COLLATOR:
            return "JSCollator";
        case JSType::JS_PLURAL_RULES:
            return "JSPluralRules";
        case JSType::JS_GENERATOR_OBJECT:
            return "JSGeneratorObject";
        case JSType::JS_GENERATOR_CONTEXT:
            return "JSGeneratorContext";
        case JSType::PROTO_CHANGE_MARKER:
            return "ProtoChangeMarker";
        case JSType::PROTOTYPE_INFO:
            return "PrototypeInfo";
        case JSType::PROGRAM:
            return "program";
        case JSType::LEXICAL_FUNCTION:
            return "LexicalFunction";
        case JSType::FUNCTION_EXTRA_INFO:
            return "FunctionExtraInfo";
        case JSType::ECMA_MODULE:
            return "EcmaModule";
        case JSType::CLASS_INFO_EXTRACTOR:
            return "ClassInfoExtractor";
        case JSType::JS_ARRAY_LIST:
            return "ArrayList";
        case JSType::FREE_OBJECT_WITH_NONE_FIELD:
            return "FreeObjectWithNoneField";
        case JSType::FREE_OBJECT_WITH_ONE_FIELD:
            return "FreeObjectWithOneField";
        case JSType::FREE_OBJECT_WITH_TWO_FIELD:
            return "FreeObjectWithTwoField";
        default: {
            PandaString ret = "unknown type ";
            return ret + static_cast<char>(type);
        }
    }
}

static void DumpArrayClass(JSThread *thread, const TaggedArray *arr, std::ostream &os)
{
    uint32_t len = arr->GetLength();
    os << " <TaggedArray[" << std::dec << len << "]>\n";
    for (uint32_t i = 0; i < len; i++) {
        JSTaggedValue val(arr->Get(i));
        if (!val.IsHole()) {
            os << std::right << std::setw(DUMP_PROPERTY_OFFSET) << i << ": ";
            val.DumpTaggedValue(thread, os);
            os << "\n";
        }
    }
}

static void DumpStringClass(const EcmaString *str, std::ostream &os)
{
    PandaString string = ConvertToPandaString(str);
    os << string;
}

static void DumpPropertyKey(JSTaggedValue key, std::ostream &os)
{
    if (key.IsString()) {
        DumpStringClass(EcmaString::Cast(key.GetTaggedObject()), os);
    } else if (key.IsSymbol()) {
        JSSymbol *sym = JSSymbol::Cast(key.GetTaggedObject());
        DumpStringClass(EcmaString::Cast(sym->GetDescription().GetTaggedObject()), os);
    } else {
        UNREACHABLE();
    }
}

static void DumpHClass(JSThread *thread, const JSHClass *jshclass, std::ostream &os, bool withDetail)
{
    os << "JSHClass :" << std::setw(DUMP_TYPE_OFFSET);
    os << "Type :" << JSHClass::DumpJSType(jshclass->GetObjectType()) << "\n";

    os << " - Prototype :" << std::setw(DUMP_TYPE_OFFSET);
    jshclass->GetPrototype().DumpTaggedValue(thread, os);
    os << "\n";
    os << " - PropertyDescriptors :" << std::setw(DUMP_TYPE_OFFSET);
    JSTaggedValue attrs = jshclass->GetLayout();
    attrs.DumpTaggedValue(thread, os);
    os << "\n";
    if (withDetail && !attrs.IsNull()) {
        LayoutInfo *layoutInfo = LayoutInfo::Cast(attrs.GetTaggedObject());
        layoutInfo->Dump(thread, os);
    }
    os << " - Transitions :" << std::setw(DUMP_TYPE_OFFSET);
    JSTaggedValue transtions = jshclass->GetTransitions();
    transtions.DumpTaggedValue(thread, os);
    os << "\n";
    if (withDetail && !transtions.IsNull()) {
        transtions.Dump(thread, os);
    }
    os << " - Parent :" << std::setw(DUMP_TYPE_OFFSET);
    jshclass->GetParent().DumpTaggedValue(thread, os);
    os << "\n";

    os << " - Flags : " << std::setw(DUMP_TYPE_OFFSET);
    os << "Ctor :" << jshclass->IsConstructor();
    os << "| Callable :" << jshclass->IsCallable();
    os << "| Extensible :" << jshclass->IsExtensible();
    os << "| ElementRepresentation :" << static_cast<int>(jshclass->GetElementRepresentation());
    os << "| NumberOfProps :" << std::dec << jshclass->NumberOfProps();
    os << "| InlinedProperties :" << std::dec << jshclass->GetInlinedProperties();
    os << "\n";
}

static void DumpDynClass(JSThread *thread, TaggedObject *obj, std::ostream &os)
{
    JSHClass *hclass = obj->GetClass();
    os << "JSHClass :" << std::setw(DUMP_TYPE_OFFSET) << " klass_(" << std::hex << hclass << ")\n";
    DumpHClass(thread, hclass, os, true);
}

static void DumpAttr(const PropertyAttributes &attr, bool fastMode, std::ostream &os)
{
    if (attr.IsAccessor()) {
        os << "(Accessor) ";
    }

    os << "Attr(";
    if (attr.IsNoneAttributes()) {
        os << "NONE";
    }
    if (attr.IsWritable()) {
        os << "W";
    }
    if (attr.IsEnumerable()) {
        os << "E";
    }
    if (attr.IsConfigurable()) {
        os << "C";
    }
    os << ")";

    os << " InlinedProps: " << attr.IsInlinedProps();

    if (fastMode) {
        os << " Order: " << std::dec << attr.GetOffset();
        os << " SortedIndex: " << std::dec << attr.GetSortedIndex();
    } else {
        os << " Order: " << std::dec << attr.GetDictionaryOrder();
    }
}

// NOLINTNEXTLINE(readability-function-size)
static void DumpObject(JSThread *thread, TaggedObject *obj, std::ostream &os)
{
    auto jsHclass = obj->GetClass();
    JSType type = jsHclass->GetObjectType();

    switch (type) {
        case JSType::HCLASS:
            return DumpDynClass(thread, obj, os);
        case JSType::TAGGED_ARRAY:
        case JSType::LINKED_HASH_SET:
        case JSType::LINKED_HASH_MAP:
        case JSType::TAGGED_DICTIONARY:
        case JSType::TEMPLATE_MAP:
            DumpArrayClass(thread, TaggedArray::Cast(obj), os);
            break;
        case JSType::STRING:
            DumpStringClass(EcmaString::Cast(obj), os);
            os << "\n";
            break;
        case JSType::JS_NATIVE_POINTER:
            break;
        case JSType::JS_OBJECT:
        case JSType::JS_GLOBAL_OBJECT:
        case JSType::JS_ERROR:
        case JSType::JS_EVAL_ERROR:
        case JSType::JS_RANGE_ERROR:
        case JSType::JS_TYPE_ERROR:
        case JSType::JS_REFERENCE_ERROR:
        case JSType::JS_URI_ERROR:
        case JSType::JS_SYNTAX_ERROR:
        case JSType::JS_ARGUMENTS:
        case JSType::JS_FUNCTION_BASE:
            JSObject::Cast(obj)->Dump(thread, os);
            break;
        case JSType::GLOBAL_ENV:
            GlobalEnv::Cast(obj)->Dump(thread, os);
            break;
        case JSType::ACCESSOR_DATA:
            break;
        case JSType::JS_FUNCTION:
            JSFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_BOUND_FUNCTION:
            JSBoundFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_SET:
            JSSet::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_MAP:
            JSMap::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_WEAK_REF:
            JSWeakRef::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_WEAK_SET:
            JSWeakSet::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_WEAK_MAP:
            JSWeakMap::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_REG_EXP:
            JSRegExp::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_DATE:
            JSDate::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ARRAY:
            JSArray::Cast(obj)->Dump(thread, os);
            break;
        case JSType::BIGINT:
            BigInt::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_TYPED_ARRAY:
        case JSType::JS_INT8_ARRAY:
        case JSType::JS_UINT8_ARRAY:
        case JSType::JS_UINT8_CLAMPED_ARRAY:
        case JSType::JS_INT16_ARRAY:
        case JSType::JS_UINT16_ARRAY:
        case JSType::JS_INT32_ARRAY:
        case JSType::JS_UINT32_ARRAY:
        case JSType::JS_FLOAT32_ARRAY:
        case JSType::JS_FLOAT64_ARRAY:
            JSTypedArray::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_PROXY:
            JSProxy::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_PRIMITIVE_REF:
            JSPrimitiveRef::Cast(obj)->Dump(thread, os);
            break;
        case JSType::SYMBOL:
            JSSymbol::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_DATA_VIEW:
            JSDataView::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ARRAY_BUFFER:
            JSArrayBuffer::Cast(obj)->Dump(thread, os);
            break;
        case JSType::PROMISE_REACTIONS:
            PromiseReaction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::PROMISE_CAPABILITY:
            PromiseCapability::Cast(obj)->Dump(thread, os);
            break;
        case JSType::PROMISE_ITERATOR_RECORD:
            PromiseIteratorRecord::Cast(obj)->Dump(thread, os);
            break;
        case JSType::PROMISE_RECORD:
            PromiseRecord::Cast(obj)->Dump(thread, os);
            break;
        case JSType::RESOLVING_FUNCTIONS_RECORD:
            ResolvingFunctionsRecord::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_PROMISE:
            JSPromise::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_PROMISE_REACTIONS_FUNCTION:
            JSPromiseReactionsFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_PROMISE_EXECUTOR_FUNCTION:
            JSPromiseExecutorFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION:
            JSPromiseAllResolveElementFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::MICRO_JOB_QUEUE:
            MicroJobQueue::Cast(obj)->Dump(thread, os);
            break;
        case JSType::PENDING_JOB:
            PendingJob::Cast(obj)->Dump(thread, os);
            break;
        case JSType::COMPLETION_RECORD:
            CompletionRecord::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_PROXY_REVOC_FUNCTION:
            JSProxyRevocFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ASYNC_FUNCTION:
            JSAsyncFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ASYNC_GENERATOR_FUNCTION:
            JSAsyncGeneratorFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION:
            JSAsyncAwaitStatusFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ASYNC_GENERATOR_RESOLVE_NEXT_FUNCTION:
            JSAsyncGeneratorResolveNextFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ASYNC_FROM_SYNC_ITERATOR_VALUE_UNWRAP_FUNCTION:
            JSAsyncFromSyncIteratorValueUnwrapFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_GENERATOR_FUNCTION:
            JSGeneratorFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_INTL_BOUND_FUNCTION:
            JSIntlBoundFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ITERATOR:
            break;
        case JSType::JS_FORIN_ITERATOR:
            JSForInIterator::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_MAP_ITERATOR:
            JSMapIterator::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_SET_ITERATOR:
            JSSetIterator::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_REG_EXP_ITERATOR:
            JSRegExpIterator::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ARRAY_ITERATOR:
            JSArrayIterator::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_STRING_ITERATOR:
            JSStringIterator::Cast(obj)->Dump(thread, os);
            break;
        case JSType::PROTOTYPE_HANDLER:
            PrototypeHandler::Cast(obj)->Dump(thread, os);
            break;
        case JSType::TRANSITION_HANDLER:
            TransitionHandler::Cast(obj)->Dump(thread, os);
            break;
        case JSType::PROPERTY_BOX:
            PropertyBox::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_REALM:
            JSRealm::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_INTL:
            JSIntl::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_LOCALE:
            JSLocale::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_DATE_TIME_FORMAT:
            JSDateTimeFormat::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_RELATIVE_TIME_FORMAT:
            JSRelativeTimeFormat::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_NUMBER_FORMAT:
            JSNumberFormat::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_COLLATOR:
            JSCollator::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_PLURAL_RULES:
            JSPluralRules::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_GENERATOR_OBJECT:
            JSGeneratorObject::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ASYNC_FUNC_OBJECT:
            JSAsyncFuncObject::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_GENERATOR_CONTEXT:
            GeneratorContext::Cast(obj)->Dump(thread, os);
            break;
        case JSType::PROTOTYPE_INFO:
            ProtoChangeDetails::Cast(obj)->Dump(thread, os);
            break;
        case JSType::PROTO_CHANGE_MARKER:
            ProtoChangeMarker::Cast(obj)->Dump(thread, os);
            break;
        case JSType::PROGRAM:
            Program::Cast(obj)->Dump(thread, os);
            break;
        case JSType::LEXICAL_FUNCTION:
            LexicalFunction::Cast(obj)->Dump(thread, os);
            break;
        case JSType::FUNCTION_EXTRA_INFO:
            JSFunctionExtraInfo::Cast(obj)->Dump(thread, os);
            break;
        case JSType::ECMA_MODULE:
            EcmaModule::Cast(obj)->Dump(thread, os);
            break;
        case JSType::CLASS_INFO_EXTRACTOR:
            ClassInfoExtractor::Cast(obj)->Dump(thread, os);
            break;
        case JSType::JS_ARRAY_LIST:
            JSArrayList::Cast(obj)->Dump(thread, os);
            break;
        case JSType::FREE_OBJECT_WITH_NONE_FIELD:
        case JSType::FREE_OBJECT_WITH_ONE_FIELD:
        case JSType::FREE_OBJECT_WITH_TWO_FIELD:
        case JSType::INTERNAL_ACCESSOR:
            // No additional info
            break;
        default:
            UNREACHABLE();
            break;
    }

    DumpHClass(thread, jsHclass, os, false);
}

void JSTaggedValue::DumpSpecialValue([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    ASSERT(IsSpecial());
    os << "[Special Value] : ";
    switch (GetRawData()) {
        case VALUE_HOLE:
            os << "Hole";
            break;
        case VALUE_NULL:
            os << "Null";
            break;
        case VALUE_FALSE:
            os << "False";
            break;
        case VALUE_TRUE:
            os << "True";
            break;
        case VALUE_UNDEFINED:
            os << "Undefined";
            break;
        case VALUE_EXCEPTION:
            os << "Exception";
            break;
        default:
            UNREACHABLE();
            break;
    }
}

void JSTaggedValue::DumpHeapObjectType([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    ASSERT(IsWeak() || IsHeapObject());
    bool isWeak = IsWeak();
    TaggedObject *obj = isWeak ? GetTaggedWeakRef() : GetTaggedObject();
    if (isWeak) {
        os << "----------Dump Weak Referent----------"
           << "\n";
    }

    JSType type = GetTaggedObject()->GetClass()->GetObjectType();
    if (type == JSType::STRING) {
        PandaString string = ConvertToPandaString(EcmaString::Cast(obj));
        os << std::left << std::setw(DUMP_TYPE_OFFSET) << "[" + string + "]";
    } else {
        std::ostringstream address;
        address << obj;
        PandaString addrStr = PandaString(address.str());

        os << std::left << std::setw(DUMP_TYPE_OFFSET) << "[" + JSHClass::DumpJSType(type) + "(" + addrStr + ")]";
    }
}

void JSTaggedValue::DumpTaggedValue(JSThread *thread, std::ostream &os) const
{
    if (IsInt()) {
        os << std::left << std::setw(DUMP_TYPE_OFFSET) << "[Int] : " << std::hex << "0x" << GetInt() << std::dec << " ("
           << GetInt() << ")";
    } else if (IsDouble()) {
        os << std::left << std::setw(DUMP_TYPE_OFFSET) << "[Double] : " << GetDouble();
    } else if (IsSpecial()) {
        DumpSpecialValue(thread, os);
    } else {
        DumpHeapObjectType(thread, os);
    }
}

void JSTaggedValue::Dump(JSThread *thread, std::ostream &os) const
{
    DumpTaggedValue(thread, os);
    os << "\n";

    if (IsHeapObject()) {
        TaggedObject *obj = GetTaggedObject();
        if (thread == nullptr) {
            thread = obj->GetJSThread();
        }
        DumpObject(thread, obj, os);
    }
}

void JSTaggedValue::D() const
{
    Dump(nullptr, std::cout);
}

void JSTaggedValue::DV(JSTaggedType val)
{
    JSTaggedValue(val).D();
}

void JSThread::DumpStack()
{
    StackWalker::Create(this).Dump(std::cout);
}

void NumberDictionary::Dump(JSThread *thread, std::ostream &os) const
{
    int size = Size();
    for (int hashIndex = 0; hashIndex < size; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole()) {
            JSTaggedValue val(GetValue(hashIndex));
            os << std::right << std::setw(DUMP_PROPERTY_OFFSET)
               << static_cast<uint32_t>(JSTaggedNumber(key).GetNumber()) << ": ";
            val.DumpTaggedValue(thread, os);
            os << " ";
            DumpAttr(GetAttributes(hashIndex), false, os);
            os << "\n";
        }
    }
}

void NameDictionary::Dump(JSThread *thread, std::ostream &os) const
{
    int size = Size();
    for (int hashIndex = 0; hashIndex < size; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole()) {
            JSTaggedValue val(GetValue(hashIndex));
            os << std::right << std::setw(DUMP_PROPERTY_OFFSET);
            DumpPropertyKey(key, os);
            os << ": ";
            val.DumpTaggedValue(thread, os);
            os << " ";
            DumpAttr(GetAttributes(hashIndex), false, os);
            os << "\n";
        }
    }
}

void GlobalDictionary::Dump(JSThread *thread, std::ostream &os) const
{
    int size = Size();
    for (int hashIndex = 0; hashIndex < size; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole()) {
            JSTaggedValue val(GetValue(hashIndex));
            os << std::right << std::setw(DUMP_PROPERTY_OFFSET);
            DumpPropertyKey(key, os);
            os << " : ";
            val.DumpTaggedValue(thread, os);
            os << " ";
            DumpAttr(GetAttributes(hashIndex), false, os);
            os << "\n";
        }
    }
}

void LayoutInfo::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    int num = NumberOfElements();
    for (int i = 0; i < num; i++) {
        JSTaggedValue key = GetKey(i);
        PropertyAttributes attr = GetAttr(i);
        os << std::right << std::setw(DUMP_PROPERTY_OFFSET);
        os << "[" << i << "]: ";
        DumpPropertyKey(key, os);
        os << " : ";
        DumpAttr(attr, true, os);
        os << "\n";
    }
}

void TransitionsDictionary::Dump(JSThread *thread, std::ostream &os) const
{
    int size = Size();
    for (int hashIndex = 0; hashIndex < size; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole()) {
            os << std::right << std::setw(DUMP_PROPERTY_OFFSET);
            DumpPropertyKey(key, os);
            os << " : ";
            GetValue(hashIndex).DumpTaggedValue(thread, os);
            os << " : ";
            GetAttributes(hashIndex).DumpTaggedValue(thread, os);
            os << "\n";
        }
    }
}

void LinkedHashSet::Dump(JSThread *thread, std::ostream &os) const
{
    int capacity = NumberOfElements() + NumberOfDeletedElements();
    for (int hashIndex = 0; hashIndex < capacity; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole()) {
            os << std::right << std::setw(DUMP_PROPERTY_OFFSET);
            key.DumpTaggedValue(thread, os);
            os << "\n";
        }
    }
}

void LinkedHashMap::Dump(JSThread *thread, std::ostream &os) const
{
    int capacity = NumberOfElements() + NumberOfDeletedElements();
    for (int hashIndex = 0; hashIndex < capacity; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole()) {
            JSTaggedValue val(GetValue(hashIndex));
            os << std::right << std::setw(DUMP_PROPERTY_OFFSET);
            key.DumpTaggedValue(thread, os);
            os << ": ";
            val.DumpTaggedValue(thread, os);
            os << "\n";
        }
    }
}

void JSObject::Dump(JSThread *thread, std::ostream &os) const
{
    JSHClass *jshclass = GetJSHClass();
    os << " - hclass: " << std::hex << jshclass << "\n";
    os << " - prototype: ";
    jshclass->GetPrototype().DumpTaggedValue(thread, os);
    os << "\n";

    TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
    os << " - elements: " << std::hex << elements;
    if (elements->GetLength() == 0) {
        os << " NONE\n";
    } else if (!elements->IsDictionaryMode()) {
        DumpArrayClass(thread, elements, os);
    } else {
        NumberDictionary *dict = NumberDictionary::Cast(elements);
        os << " <NumberDictionary[" << std::dec << dict->EntriesCount() << "]>\n";
        dict->Dump(thread, os);
    }

    TaggedArray *properties = TaggedArray::Cast(GetProperties().GetTaggedObject());
    os << " - properties: " << std::hex << properties;
    if (IsJSGlobalObject()) {
        GlobalDictionary *dict = GlobalDictionary::Cast(properties);
        os << " <GlobalDictionary[" << std::dec << dict->EntriesCount() << "]>\n";
        dict->Dump(thread, os);
        return;
    }

    if (!properties->IsDictionaryMode()) {
        JSTaggedValue attrs = jshclass->GetLayout();
        if (attrs.IsNull()) {
            return;
        }

        LayoutInfo *layoutInfo = LayoutInfo::Cast(attrs.GetTaggedObject());
        int propNumber = jshclass->NumberOfProps();
        os << " <LayoutInfo[" << std::dec << propNumber << "]>\n";
        for (int i = 0; i < propNumber; i++) {
            JSTaggedValue key = layoutInfo->GetKey(i);
            PropertyAttributes attr = layoutInfo->GetAttr(i);
            ASSERT(i == static_cast<int>(attr.GetOffset()));
            os << "     " << std::right << std::setw(DUMP_PROPERTY_OFFSET);
            DumpPropertyKey(key, os);
            os << ": (";
            JSTaggedValue val;
            if (attr.IsInlinedProps()) {
                val = GetPropertyInlinedProps(i);
            } else {
                val = properties->Get(i - jshclass->GetInlinedProperties());
            }
            val.DumpTaggedValue(thread, os);
            os << ") ";
            DumpAttr(attr, true, os);
            os << "\n";
        }
    } else {
        NameDictionary *dict = NameDictionary::Cast(properties);
        os << " <NameDictionary[" << std::dec << dict->EntriesCount() << "]>\n";
        dict->Dump(thread, os);
    }
}

void AccessorData::Dump(JSThread *thread, std::ostream &os) const
{
    auto *hclass = GetClass();
    if (hclass->GetObjectType() == JSType::INTERNAL_ACCESSOR) {
        os << " - Getter: " << reinterpret_cast<void *>(GetGetter().GetTaggedObject()) << "\n";
        os << " - Setter: " << reinterpret_cast<void *>(GetSetter().GetTaggedObject()) << "\n";
        return;
    }

    os << " - Getter: ";
    GetGetter().DumpTaggedValue(thread, os);
    os << "\n";

    os << " - Setter: ";
    GetSetter().DumpTaggedValue(thread, os);
    os << "\n";
}

void Program::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - Location: ";
    GetLocation().D();
    os << "\n";
    os << " - ConstantPool: ";
    GetConstantPool().D();
    os << "\n";
    os << " - MainFunction: ";
    GetMainFunction().D();
    os << "\n";
    PandaList<JSMethod> *methods = GetMethodsData();
    os << " - NumberMethods: " << methods->size() << "\n";
}

void ConstantPool::Dump(JSThread *thread, std::ostream &os) const
{
    DumpArrayClass(thread, this, os);
}

void JSFunction::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - ProtoOrDynClass: ";
    GetProtoOrDynClass().D();
    os << "\n";
    os << " - LexicalEnv: ";
    GetLexicalEnv().D();
    os << "\n";
    os << " - HomeObject: ";
    GetHomeObject().D();
    os << "\n";
    os << " - FunctionInfoFlag: ";
    GetFunctionInfoFlag().D();
    os << "\n";
    os << " - FunctionExtraInfo: ";
    GetFunctionExtraInfo().D();
    os << "\n";
    os << " - ConstantPool: ";
    GetConstantPool().D();
    os << "\n";
    os << " - ProfileTypeInfo: ";
    GetProfileTypeInfo().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSHClass::Dump(JSThread *thread, std::ostream &os) const
{
    DumpHClass(thread, this, os, true);
}

void JSConstructorFunction::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - ComputedFields: ";
    GetComputedFields().DumpTaggedValue(thread, os);
    os << "\n";
    os << " - PrivateFields: ";
    GetPrivateFields().DumpTaggedValue(thread, os);
    os << "\n";

    JSObject::Dump(thread, os);
}

void JSBoundFunction::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - BoundTarget: ";
    GetBoundTarget().DumpTaggedValue(thread, os);
    os << "\n";

    os << " - BoundThis: ";
    GetBoundThis().DumpTaggedValue(thread, os);
    os << "\n";

    os << " - BoundArguments: ";
    GetBoundArguments().DumpTaggedValue(thread, os);
    os << "\n";

    JSObject::Dump(thread, os);
}

void JSPrimitiveRef::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - SubValue : ";
    GetValue().DumpTaggedValue(thread, os);
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSDate::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - time: " << GetTime().GetDouble() << "\n";
    os << " - localOffset: " << GetLocalOffset().GetDouble() << "\n";
    JSObject::Dump(thread, os);
}

void JSMap::Dump(JSThread *thread, std::ostream &os) const
{
    LinkedHashMap *map = LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject());
    os << " - elements: " << std::dec << map->NumberOfElements() << "\n";
    os << " - deleted-elements: " << std::dec << map->NumberOfDeletedElements() << "\n";
    os << " - capacity: " << std::dec << map->Capacity() << "\n";
    JSObject::Dump(thread, os);

    os << " <NameDictionary[" << map->NumberOfElements() << "]>\n";
    map->Dump(thread, os);
}

void JSForInIterator::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - Object : ";
    GetObject().DumpTaggedValue(thread, os);
    os << "\n";
    os << " - WasVisited : ";
    GetWasVisited().DumpTaggedValue(thread, os);
    os << "\n";
    os << " - VisitedKeys : ";
    GetVisitedKeys().DumpTaggedValue(thread, os);
    os << "\n";
    os << " - RemainingKeys : ";
    GetRemainingKeys().DumpTaggedValue(thread, os);
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSMapIterator::Dump(JSThread *thread, std::ostream &os) const
{
    LinkedHashMap *map = LinkedHashMap::Cast(GetIteratedMap().GetTaggedObject());
    os << " - elements: " << std::dec << map->NumberOfElements() << "\n";
    os << " - deleted-elements: " << std::dec << map->NumberOfDeletedElements() << "\n";
    os << " - capacity: " << std::dec << map->Capacity() << "\n";
    os << " - nextIndex: " << std::dec << GetNextIndex().GetInt() << "\n";
    os << " - IterationKind: " << std::dec << GetIterationKind().GetInt() << "\n";
    JSObject::Dump(thread, os);

    os << " <NameDictionary[" << map->NumberOfElements() << "]>\n";
    map->Dump(thread, os);
}

void JSSet::Dump(JSThread *thread, std::ostream &os) const
{
    LinkedHashSet *set = LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject());
    os << " - elements: " << std::dec << set->NumberOfElements() << "\n";
    os << " - deleted-elements: " << std::dec << set->NumberOfDeletedElements() << "\n";
    os << " - capacity: " << std::dec << set->Capacity() << "\n";
    JSObject::Dump(thread, os);

    os << " <NameDictionary[" << set->NumberOfElements() << "]>\n";
    set->Dump(thread, os);
}

void JSWeakRef::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - referent: " << (GetReferent().IsUndefined() ? "undefined\n" : "<object>\n");
    JSObject::Dump(thread, os);
}

void JSWeakMap::Dump(JSThread *thread, std::ostream &os) const
{
    LinkedHashMap *map = LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject());
    os << " - length: " << std::dec << GetSize() << "\n";
    os << " - elements: " << std::dec << map->NumberOfElements() << "\n";
    os << " - deleted-elements: " << std::dec << map->NumberOfDeletedElements() << "\n";
    os << " - capacity: " << std::dec << map->Capacity() << "\n";
    JSObject::Dump(thread, os);

    os << " <NameDictionary[" << map->NumberOfElements() << "]>\n";
    map->Dump(thread, os);
}

void JSWeakSet::Dump(JSThread *thread, std::ostream &os) const
{
    LinkedHashSet *set = LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject());
    os << " - size: " << std::dec << GetSize() << "\n";
    os << " - elements: " << std::dec << set->NumberOfElements() << "\n";
    os << " - deleted-elements: " << std::dec << set->NumberOfDeletedElements() << "\n";
    os << " - capacity: " << std::dec << set->Capacity() << "\n";
    JSObject::Dump(thread, os);

    os << " <NameDictionary[" << set->NumberOfElements() << "]>\n";
    set->Dump(thread, os);
}

void JSSetIterator::Dump(JSThread *thread, std::ostream &os) const
{
    LinkedHashSet *set = LinkedHashSet::Cast(GetIteratedSet().GetTaggedObject());
    os << " - elements: " << std::dec << set->NumberOfElements() << "\n";
    os << " - deleted-elements: " << std::dec << set->NumberOfDeletedElements() << "\n";
    os << " - capacity: " << std::dec << set->Capacity() << "\n";
    os << " - nextIndex: " << std::dec << GetNextIndex().GetInt() << "\n";
    os << " - IterationKind: " << std::dec << GetIterationKind().GetInt() << "\n";
    JSObject::Dump(thread, os);

    os << " <NameDictionary[" << set->NumberOfElements() << "]>\n";
    set->Dump(thread, os);
}

void JSRegExpIterator::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - IteratingRegExp: ";
    GetIteratingRegExp().D();
    os << "\n";
    os << " - IteratedString: ";
    GetIteratedString().D();
    os << "\n";
    os << " - Global: " << std::dec << GetGlobal() << "\n";
    os << " - Unicode: " << std::dec << GetUnicode() << "\n";
    os << " - Done: " << std::dec << GetDone() << "\n";
    JSObject::Dump(thread, os);
}

void JSArray::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - length: " << std::dec << GetArrayLength() << "\n";
    JSObject::Dump(thread, os);
}

void BigInt::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - data: ";
    GetData().D();
    os << "\n";
    os << " - value : " << ToStdString(thread, DECIMAL) << "\n";
    os << " - sign : " << GetSign() << "\n";
}

void JSArrayList::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - length: " << std::dec << GetLength().GetArrayLength() << "\n";
    JSObject::Dump(thread, os);
}

void JSArrayIterator::Dump(JSThread *thread, std::ostream &os) const
{
    JSArray *array = JSArray::Cast(GetIteratedArray().GetTaggedObject());
    os << " - length: " << std::dec << array->GetArrayLength() << "\n";
    os << " - nextIndex: " << std::dec << GetNextIndex().GetInt() << "\n";
    os << " - IterationKind: " << std::dec << GetIterationKind().GetInt() << "\n";
    JSObject::Dump(thread, os);
}

void JSStringIterator::Dump(JSThread *thread, std::ostream &os) const
{
    EcmaString *str = EcmaString::Cast(GetIteratedString().GetTaggedObject());
    os << " - IteratedString: " << str->GetCString().get() << "\n";
    os << " - StringIteratorNextIndex: " << std::dec << GetStringIteratorNextIndex().GetInt() << "\n";
    JSObject::Dump(thread, os);
}
void JSTypedArray::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - viewed-array-buffer: ";
    GetViewedArrayBuffer().D();
    os << " - typed-array-name: ";
    GetTypedArrayName().D();
    os << " - byte-length: ";
    GetByteLength().D();
    os << " - byte-offset: ";
    GetByteOffset().D();
    os << " - array-length: ";
    GetArrayLength().D();
    JSObject::Dump(thread, os);
}

void JSRegExp::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - LastIndex: ";
    GetLastIndex().D();
    os << "\n";
    os << " - ByteCodeBuffer: ";
    GetByteCodeBuffer().D();
    os << "\n";
    os << " - OriginalSource: ";
    GetOriginalSource().D();
    os << "\n";
    os << " - OriginalFlags: ";
    GetOriginalFlags().D();
    os << "\n";
    os << " - Length: ";
    GetLength().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSProxy::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - Target: ";
    os << "\n";
    JSObject::Cast(GetTarget().GetTaggedObject())->Dump(thread, os);
    os << " - Handler: ";
    os << "\n";
    JSObject::Cast(GetHandler().GetTaggedObject())->Dump(thread, os);
    os << "\n";
}

void JSSymbol::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - hash-field: ";
    JSTaggedValue hashField = GetHashField();
    hashField.D();
    os << " - flags: ";
    JSTaggedValue flags = GetFlags();
    flags.D();
    os << " - description: ";
    JSTaggedValue description = GetDescription();
    description.D();
}

void LexicalEnv::Dump(JSThread *thread, std::ostream &os) const
{
    DumpArrayClass(thread, this, os);
}

// NOLINTNEXTLINE(readability-function-size)
void GlobalEnv::Dump(JSThread *thread, std::ostream &os) const
{
    auto globalConst = thread->GlobalConstants();
    os << " - ObjectFunction: ";
    GetObjectFunction().GetTaggedValue().Dump(thread, os);
    os << " - FunctionFunction: ";
    GetFunctionFunction().GetTaggedValue().Dump(thread, os);
    os << " - NumberFunction: ";
    GetNumberFunction().GetTaggedValue().Dump(thread, os);
    os << " - BigIntFunction: ";
    GetBigIntFunction().GetTaggedValue().Dump(thread, os);
    os << " - DateFunction: ";
    GetDateFunction().GetTaggedValue().Dump(thread, os);
    os << " - BooleanFunction: ";
    GetBooleanFunction().GetTaggedValue().Dump(thread, os);
    os << " - ErrorFunction: ";
    GetErrorFunction().GetTaggedValue().Dump(thread, os);
    os << " - ArrayFunction: ";
    GetArrayFunction().GetTaggedValue().Dump(thread, os);
    os << " - TypedArrayFunction: ";
    GetTypedArrayFunction().GetTaggedValue().Dump(thread, os);
    os << " - Int8ArrayFunction: ";
    GetInt8ArrayFunction().GetTaggedValue().Dump(thread, os);
    os << " - Uint8ArrayFunction: ";
    GetUint8ArrayFunction().GetTaggedValue().Dump(thread, os);
    os << " - Uint8ClampedArrayFunction: ";
    GetUint8ClampedArrayFunction().GetTaggedValue().Dump(thread, os);
    os << " - Int16ArrayFunction: ";
    GetInt16ArrayFunction().GetTaggedValue().Dump(thread, os);
    os << " - ArrayBufferFunction: ";
    GetArrayBufferFunction().GetTaggedValue().Dump(thread, os);
    os << " - SymbolFunction: ";
    GetSymbolFunction().GetTaggedValue().Dump(thread, os);
    os << " - RangeErrorFunction: ";
    GetRangeErrorFunction().GetTaggedValue().Dump(thread, os);
    os << " - ReferenceErrorFunction: ";
    GetReferenceErrorFunction().GetTaggedValue().Dump(thread, os);
    os << " - TypeErrorFunction: ";
    GetTypeErrorFunction().GetTaggedValue().Dump(thread, os);
    os << " - URIErrorFunction: ";
    GetURIErrorFunction().GetTaggedValue().Dump(thread, os);
    os << " - SyntaxErrorFunction: ";
    GetSyntaxErrorFunction().GetTaggedValue().Dump(thread, os);
    os << " - EvalErrorFunction: ";
    GetEvalErrorFunction().GetTaggedValue().Dump(thread, os);
    os << " - RegExpFunction: ";
    GetRegExpFunction().GetTaggedValue().Dump(thread, os);
    os << " - SetFunction: ";
    GetSetFunction().GetTaggedValue().Dump(thread, os);
    os << " - MapFunction: ";
    GetMapFunction().GetTaggedValue().Dump(thread, os);
    os << " - WeakSetFunction: ";
    GetWeakSetFunction().GetTaggedValue().Dump(thread, os);
    os << " - WeakMapFunction: ";
    GetWeakMapFunction().GetTaggedValue().Dump(thread, os);
    os << " - MathFunction: ";
    GetMathFunction().GetTaggedValue().Dump(thread, os);
    os << " - JsonFunction: ";
    GetJsonFunction().GetTaggedValue().Dump(thread, os);
    os << " - StringFunction: ";
    GetStringFunction().GetTaggedValue().Dump(thread, os);
    os << " - ProxyFunction: ";
    GetProxyFunction().GetTaggedValue().Dump(thread, os);
    os << " - ReflectFunction: ";
    GetReflectFunction().GetTaggedValue().Dump(thread, os);
    os << " - AsyncFunction: ";
    GetAsyncFunction().GetTaggedValue().Dump(thread, os);
    os << " - AsyncFunctionPrototype: ";
    GetAsyncFunctionPrototype().GetTaggedValue().Dump(thread, os);
    os << " - JSGlobalObject: ";
    GetJSGlobalObject().GetTaggedValue().Dump(thread, os);
    os << " - EmptyArray: ";
    GetEmptyArray().GetTaggedValue().Dump(thread, os);
    os << " - EmptyString ";
    globalConst->GetEmptyString().Dump(thread, os);
    os << " - EmptyTaggedQueue: ";
    GetEmptyTaggedQueue().GetTaggedValue().Dump(thread, os);
    os << " - PrototypeString: ";
    globalConst->GetPrototypeString().Dump(thread, os);
    os << " - HasInstanceSymbol: ";
    GetHasInstanceSymbol().GetTaggedValue().Dump(thread, os);
    os << " - IsConcatSpreadableSymbol: ";
    GetIsConcatSpreadableSymbol().GetTaggedValue().Dump(thread, os);
    os << " - ToStringTagSymbol: ";
    GetToStringTagSymbol().GetTaggedValue().Dump(thread, os);
    os << " - IteratorSymbol: ";
    GetIteratorSymbol().GetTaggedValue().Dump(thread, os);
    os << " - MatchSymbol: ";
    GetMatchSymbol().GetTaggedValue().Dump(thread, os);
    os << " - ReplaceSymbol: ";
    GetReplaceSymbol().GetTaggedValue().Dump(thread, os);
    os << " - SearchSymbol: ";
    GetSearchSymbol().GetTaggedValue().Dump(thread, os);
    os << " - SpeciesSymbol: ";
    GetSpeciesSymbol().GetTaggedValue().Dump(thread, os);
    os << " - SplitSymbol: ";
    GetSplitSymbol().GetTaggedValue().Dump(thread, os);
    os << " - ToPrimitiveSymbol: ";
    GetToPrimitiveSymbol().GetTaggedValue().Dump(thread, os);
    os << " - UnscopablesSymbol: ";
    GetUnscopablesSymbol().GetTaggedValue().Dump(thread, os);
    os << " - HoleySymbol: ";
    GetHoleySymbol().GetTaggedValue().Dump(thread, os);
    os << " - ConstructorString: ";
    globalConst->GetConstructorString().Dump(thread, os);
    os << " - IteratorPrototype: ";
    GetIteratorPrototype().GetTaggedValue().Dump(thread, os);
    os << " - ForinIteratorPrototype: ";
    GetForinIteratorPrototype().GetTaggedValue().Dump(thread, os);
    os << " - StringIterator: ";
    GetStringIteratorFunction().GetTaggedValue().Dump(thread, os);
    os << " - MapIteratorPrototype: ";
    GetMapIteratorPrototype().GetTaggedValue().Dump(thread, os);
    os << " - SetIteratorPrototype: ";
    GetSetIteratorPrototype().GetTaggedValue().Dump(thread, os);
    os << " - RegExpIteratorPrototype: ";
    GetRegExpIteratorPrototype().GetTaggedValue().Dump(thread, os);
    os << " - ArrayIteratorPrototype: ";
    GetArrayIteratorPrototype().GetTaggedValue().Dump(thread, os);
    os << " - StringIteratorPrototype: ";
    GetStringIteratorPrototype().GetTaggedValue().Dump(thread, os);
    os << " - LengthString: ";
    globalConst->GetLengthString().Dump(thread, os);
    os << " - ValueString: ";
    globalConst->GetValueString().Dump(thread, os);
    os << " - WritableString: ";
    globalConst->GetWritableString().Dump(thread, os);
    os << " - GetString: ";
    globalConst->GetGetString().Dump(thread, os);
    os << " - SetString: ";
    globalConst->GetSetString().Dump(thread, os);
    os << " - EnumerableString: ";
    globalConst->GetEnumerableString().Dump(thread, os);
    os << " - ConfigurableString: ";
    globalConst->GetConfigurableString().Dump(thread, os);
    os << " - NameString: ";
    globalConst->GetNameString().Dump(thread, os);
    os << " - ValueOfString: ";
    globalConst->GetValueOfString().Dump(thread, os);
    os << " - ToStringString: ";
    globalConst->GetToStringString().Dump(thread, os);
    os << " - ToLocaleStringString: ";
    globalConst->GetToLocaleStringString().Dump(thread, os);
    os << " - UndefinedString: ";
    globalConst->GetUndefinedString().Dump(thread, os);
    os << " - NullString: ";
    globalConst->GetNullString().Dump(thread, os);
    os << " - TrueString: ";
    globalConst->GetTrueString().Dump(thread, os);
    os << " - FalseString: ";
    globalConst->GetFalseString().Dump(thread, os);
    os << " - RegisterSymbols: ";
    GetRegisterSymbols().GetTaggedValue().Dump(thread, os);
    os << " - ThrowTypeError: ";
    GetThrowTypeError().GetTaggedValue().Dump(thread, os);
    os << " - GetPrototypeOfString: ";
    globalConst->GetGetPrototypeOfString().Dump(thread, os);
    os << " - SetPrototypeOfString: ";
    globalConst->GetSetPrototypeOfString().Dump(thread, os);
    os << " - IsExtensibleString: ";
    globalConst->GetIsExtensibleString().Dump(thread, os);
    os << " - PreventExtensionsString: ";
    globalConst->GetPreventExtensionsString().Dump(thread, os);
    os << " - GetOwnPropertyDescriptorString: ";
    globalConst->GetGetOwnPropertyDescriptorString().Dump(thread, os);
    os << " - DefinePropertyString: ";
    globalConst->GetDefinePropertyString().Dump(thread, os);
    os << " - HasString: ";
    globalConst->GetHasString().Dump(thread, os);
    os << " - DeletePropertyString: ";
    globalConst->GetDeletePropertyString().Dump(thread, os);
    os << " - EnumerateString: ";
    globalConst->GetEnumerateString().Dump(thread, os);
    os << " - OwnKeysString: ";
    globalConst->GetOwnKeysString().Dump(thread, os);
    os << " - ApplyString: ";
    globalConst->GetApplyString().Dump(thread, os);
    os << " - ProxyString: ";
    globalConst->GetProxyString().Dump(thread, os);
    os << " - RevokeString: ";
    globalConst->GetRevokeString().Dump(thread, os);
    os << " - ProxyConstructString: ";
    globalConst->GetProxyConstructString().Dump(thread, os);
    os << " - ProxyCallString: ";
    globalConst->GetProxyCallString().Dump(thread, os);
    os << " - DoneString: ";
    globalConst->GetDoneString().Dump(thread, os);
    os << " - NegativeZeroString: ";
    globalConst->GetNegativeZeroString().Dump(thread, os);
    os << " - NextString: ";
    globalConst->GetNextString().Dump(thread, os);
    os << " - PromiseThenString: ";
    globalConst->GetPromiseThenString().Dump(thread, os);
    os << " - PromiseFunction: ";
    GetPromiseFunction().GetTaggedValue().Dump(thread, os);
    os << " - PromiseReactionJob: ";
    GetPromiseReactionJob().GetTaggedValue().Dump(thread, os);
    os << " - PromiseResolveThenableJob: ";
    GetPromiseResolveThenableJob().GetTaggedValue().Dump(thread, os);
    os << " - ScriptJobString: ";
    globalConst->GetScriptJobString().Dump(thread, os);
    os << " - PromiseString: ";
    globalConst->GetPromiseString().Dump(thread, os);
    os << " - IdentityString: ";
    globalConst->GetIdentityString().Dump(thread, os);
    os << " - AsyncFunctionString: ";
    globalConst->GetAsyncFunctionString().Dump(thread, os);
    os << " - ThrowerString: ";
    globalConst->GetThrowerString().Dump(thread, os);
    os << " - Undefined: ";
    globalConst->GetUndefined().Dump(thread, os);
}

void JSDataView::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - data-view: ";
    GetDataView().D();
    os << " - buffer: ";
    GetViewedArrayBuffer().D();
    os << " - byte-length: ";
    GetByteLength().D();
    os << " - byte-offset: ";
    GetByteOffset().D();
}

void JSArrayBuffer::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - byte-length: ";
    GetArrayBufferByteLength().D();
    os << " - buffer-data: ";
    GetArrayBufferData().D();
    os << " - Shared: ";
    GetShared().D();
}

void PromiseReaction::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - promise-capability: ";
    GetPromiseCapability().D();
    os << " - type: ";
    GetType().D();
    os << " - handler: ";
    GetHandler().D();
}

void PromiseCapability::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - promise: ";
    GetPromise().D();
    os << " - resolve: ";
    GetResolve().D();
    os << " - reject: ";
    GetReject().D();
}

void PromiseIteratorRecord::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - iterator: ";
    GetIterator().D();
    os << " - done: ";
    GetDone().D();
}

void PromiseRecord::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - value: ";
    GetValue().D();
}

void ResolvingFunctionsRecord::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - resolve-function: ";
    GetResolveFunction().D();
    os << " - reject-function: ";
    GetRejectFunction().D();
}

void JSPromise::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - promise-state: ";
    GetPromiseState().D();
    os << " - promise-result: ";
    GetPromiseResult().D();
    os << " - promise-fulfill-reactions: ";
    GetPromiseFulfillReactions().D();
    os << " - promise-reject-reactions: ";
    GetPromiseRejectReactions().D();
    os << " - promise-is-handled: ";
    GetPromiseIsHandled().D();
    JSObject::Dump(thread, os);
}

void JSPromiseReactionsFunction::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - promise: ";
    GetPromise().D();
    os << " - already-resolved: ";
    GetAlreadyResolved().D();
    JSObject::Dump(thread, os);
}

void JSPromiseExecutorFunction::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - capability: ";
    GetCapability().D();
    JSObject::Dump(thread, os);
}

void JSPromiseAllResolveElementFunction::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - index: ";
    GetIndex().D();
    os << " - values: ";
    GetValues().D();
    os << " - capability: ";
    GetCapabilities().D();
    os << " - remaining-elements: ";
    GetRemainingElements().D();
    os << " - already-called: ";
    GetAlreadyCalled().D();
    JSObject::Dump(thread, os);
}

void MicroJobQueue::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - promise-job-queue: ";
    GetPromiseJobQueue().D();
    os << " - script-job-queue: ";
    GetScriptJobQueue().D();
}

void PendingJob::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - job: ";
    GetJob().D();
    os << " - arguments: ";
    GetArguments().D();
}

void CompletionRecord::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - type: ";
    GetType().D();
    os << " - value: ";
    GetValue().D();
}

void JSProxyRevocFunction::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - RevocableProxy: ";
    os << "\n";
    GetRevocableProxy().D();
    os << "\n";
}

void JSAsyncFunction::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    JSFunction::Dump(thread, os);
}

void JSAsyncGeneratorFunction::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    JSFunction::Dump(thread, os);
}

void JSAsyncAwaitStatusFunction::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - AsyncContext: ";
    os << "\n";
    GetAsyncContext().D();
    os << "\n";
}

void JSAsyncGeneratorResolveNextFunction::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - AsyncGenerator: ";
    os << "\n";
    JSObject::Cast(GetAsyncGenerator().GetHeapObject())->Dump(thread, os);
    os << "\n";
}

void JSAsyncFromSyncIteratorValueUnwrapFunction::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - Done: ";
    os << "\n";
    GetDone().D();
    os << "\n";
}

void JSGeneratorFunction::Dump(JSThread *thread, std::ostream &os) const
{
    JSFunction::Dump(thread, os);
}

void JSIntlBoundFunction::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - NumberFormat: ";
    GetNumberFormat().D();
    os << "\n";
    os << " - DateTimeFormat: ";
    GetDateTimeFormat().D();
    os << "\n";
    os << " - Collator: ";
    GetCollator().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void PropertyBox::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - Value: ";
    GetValue().D();
    os << "\n";
}

void PrototypeHandler::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - HandlerInfo: ";
    GetHandlerInfo().D();
    os << "\n";
    os << " - ProtoCell: ";
    GetHandlerInfo().D();
    os << "\n";
    os << " - Holder: ";
    GetHandlerInfo().D();
    os << "\n";
}

void TransitionHandler::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - HandlerInfo: ";
    GetHandlerInfo().D();
    os << "\n";
    os << " - TransitionHClass: ";
    GetTransitionHClass().D();
    os << "\n";
}

void JSRealm::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - Value: ";
    GetValue().D();
    os << "\n";
    os << " - GlobalEnv: ";
    GetGlobalEnv().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSIntl::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - FallbackSymbol: ";
    GetFallbackSymbol().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSLocale::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - IcuField: ";
    GetIcuField().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSDateTimeFormat::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - Locale: ";
    GetLocale().D();
    os << "\n";
    os << " - Calendar: ";
    GetCalendar().D();
    os << "\n";
    os << " - NumberingSystem: ";
    GetNumberingSystem().D();
    os << "\n";
    os << " - TimeZone: ";
    GetTimeZone().D();
    os << "\n";
    os << " - HourCycle: ";
    GetHourCycle().D();
    os << "\n";
    os << " - LocaleIcu: ";
    GetLocaleIcu().D();
    os << "\n";
    os << " - SimpleDateTimeFormatIcu: ";
    GetSimpleDateTimeFormatIcu().D();
    os << "\n";
    os << " - Iso8601: ";
    GetIso8601().D();
    os << "\n";
    os << " - DateStyle: ";
    GetDateStyle().D();
    os << "\n";
    os << " - TimeStyle: ";
    GetTimeStyle().D();
    os << "\n";
    os << " - BoundFormat: ";
    GetBoundFormat().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSRelativeTimeFormat::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - Locale: ";
    GetLocale().D();
    os << "\n";
    os << " - InitializedRelativeTimeFormat: ";
    GetInitializedRelativeTimeFormat().D();
    os << "\n";
    os << " - NumberingSystem: ";
    GetNumberingSystem().D();
    os << "\n";
    os << " - Style: ";
    GetStyle().D();
    os << "\n";
    os << " - Numeric: ";
    GetNumeric().D();
    os << "\n";
    os << " - AvailableLocales: ";
    GetAvailableLocales().D();
    os << "\n";
    os << " - IcuField: ";
    GetIcuField().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSNumberFormat::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - Locale: ";
    GetLocale().D();
    os << "\n"
       << " - NumberingSystem: ";
    GetNumberingSystem().D();
    os << "\n"
       << " - Style: ";
    GetStyle().D();
    os << "\n"
       << " - Currency: ";
    GetCurrency().D();
    os << "\n"
       << " - CurrencyDisplay: ";
    GetCurrencyDisplay().D();
    os << "\n"
       << " - CurrencySign: ";
    GetCurrencySign().D();
    os << "\n"
       << " - Unit: ";
    GetUnit().D();
    os << "\n"
       << " - UnitDisplay: ";
    GetUnitDisplay().D();
    os << "\n"
       << " - MinimumIntegerDigits: ";
    GetMinimumIntegerDigits().D();
    os << "\n"
       << " - MinimumFractionDigits: ";
    GetMinimumFractionDigits().D();
    os << "\n"
       << " - MaximumFractionDigits: ";
    GetMaximumFractionDigits().D();
    os << "\n"
       << " - MinimumSignificantDigits: ";
    GetMinimumSignificantDigits().D();
    os << "\n"
       << " - MaximumSignificantDigits: ";
    GetMaximumSignificantDigits().D();
    os << "\n"
       << " - UseGrouping: ";
    GetUseGrouping().D();
    os << "\n"
       << " - RoundingType: ";
    GetUseGrouping().D();
    os << "\n"
       << " - Notation: ";
    GetMinimumIntegerDigits().D();
    os << "\n"
       << " - CompactDisplay: ";
    GetMaximumSignificantDigits().D();
    os << "\n"
       << " - SignDisplay: ";
    GetMinimumFractionDigits().D();
    os << "\n"
       << " - BoundFormat: ";
    GetMaximumFractionDigits().D();
    os << "\n"
       << " - IcuField: ";
    GetMinimumSignificantDigits().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSCollator::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - IcuField: ";
    GetIcuField().D();
    os << "\n";
    os << " - Locale: ";
    GetLocale().D();
    os << "\n";
    os << " - Usage: ";
    GetUsage().D();
    os << "\n";
    os << " - Sensitivity: ";
    GetSensitivity().D();
    os << "\n";
    os << " - IgnorePunctuation: ";
    GetIgnorePunctuation().D();
    os << "\n";
    os << " - Collation: ";
    GetCollation().D();
    os << "\n";
    os << " - Numeric: ";
    GetNumeric().D();
    os << "\n";
    os << " - CaseFirst: ";
    GetCaseFirst().D();
    os << "\n";
    os << " - BoundCompare: ";
    GetBoundCompare().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSPluralRules::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - Locale: ";
    GetLocale().D();
    os << "\n";
    os << " - InitializedPluralRules: ";
    GetInitializedPluralRules().D();
    os << "\n";
    os << " - Type: ";
    GetType().D();
    os << "\n";
    os << " - MinimumIntegerDigits: ";
    GetMinimumIntegerDigits().D();
    os << "\n";
    os << " - MinimumFractionDigits: ";
    GetMinimumFractionDigits().D();
    os << "\n";
    os << " - MaximumFractionDigits: ";
    GetMaximumFractionDigits().D();
    os << "\n";
    os << " - MinimumSignificantDigits: ";
    GetMinimumSignificantDigits().D();
    os << "\n";
    os << " - MaximumSignificantDigits: ";
    GetMaximumSignificantDigits().D();
    os << "\n";
    os << " - RoundingType: ";
    GetRoundingType().D();
    os << "\n";
    os << " - IcuPR: ";
    GetIcuPR().D();
    os << "\n";
    os << " - IcuNF: ";
    GetIcuNF().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSGeneratorObject::Dump(JSThread *thread, std::ostream &os) const
{
    os << " - GeneratorState: ";
    GetGeneratorState().D();
    os << "\n";
    os << " - GeneratorContext: ";
    GetGeneratorContext().D();
    os << "\n";
    os << " - ResumeResult: ";
    GetResumeResult().D();
    os << "\n";
    os << " - ResumeMode: ";
    GetResumeMode().D();
    os << "\n";
    JSObject::Dump(thread, os);
}

void JSAsyncFuncObject::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - Promise: ";
    GetPromise().D();
    os << "\n";
}

void GeneratorContext::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - RegsArray: ";
    GetRegsArray().D();
    os << "\n";
    os << " - Method: ";
    GetMethod().D();
    os << "\n";
    os << " - Acc: ";
    GetAcc().D();
    os << "\n";
    os << " - NRegs: ";
    GetNRegs().D();
    os << "\n";
    os << " - BCOffset: ";
    GetBCOffset().D();
    os << "\n";
    os << " - GeneratorObject: ";
    GetGeneratorObject().D();
    os << "\n";
    os << " - LexicalEnv: ";
    GetLexicalEnv().D();
    os << "\n";
}

void ProtoChangeMarker::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - HasChanged: " << GetHasChanged() << "\n";
}

void ProtoChangeDetails::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - ChangeListener: ";
    GetChangeListener().D();
    os << "\n";
    os << " - RegisterIndex: ";
    GetRegisterIndex().D();
    os << "\n";
}

void LexicalFunction::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - Name: ";
    GetName().D();
    os << "\n";
    os << " - NumberVRegs: ";
    GetNumberVRegs().D();
    os << "\n";
    os << " - NumberICSlots: ";
    GetNumberICSlots().D();
    os << "\n";
    os << " - Bytecode: ";
    GetBytecode().D();
    os << "\n";
    os << " - Program: ";
    GetProgram().D();
    os << "\n";
}

void JSFunctionExtraInfo::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - Callback: ";
    GetCallback().D();
    os << "\n";
    os << " - Data: ";
    GetData().D();
    os << "\n";
}

void EcmaModule::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - NameDictionary: ";
    GetNameDictionary().D();
    os << "\n";
}

void ClassInfoExtractor::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const
{
    os << " - PrototypeHClass: ";
    GetPrototypeHClass().D();
    os << "\n";
    os << " - NonStaticKeys: ";
    GetNonStaticKeys().D();
    os << "\n";
    os << " - NonStaticProperties: ";
    GetNonStaticProperties().D();
    os << "\n";
    os << " - NonStaticElements: ";
    GetNonStaticElements().D();
    os << "\n";
    os << " - ConstructorHClass: ";
    GetConstructorHClass().D();
    os << "\n";
    os << " - StaticKeys: ";
    GetStaticKeys().D();
    os << "\n";
    os << " - StaticProperties: ";
    GetStaticProperties().D();
    os << "\n";
    os << " - StaticElements: ";
    GetStaticElements().D();
    os << "\n";
}

// ########################################################################################
// Dump for Snapshot
// ########################################################################################
static void DumpArrayClass([[maybe_unused]] JSThread *thread, const TaggedArray *arr,
                           std::vector<std::pair<PandaString, JSTaggedValue>> &vec)
{
    uint32_t len = arr->GetLength();
    for (uint32_t i = 0; i < len; i++) {
        JSTaggedValue val(arr->Get(i));
        PandaString str = ToPandaString(i);
        vec.emplace_back(std::make_pair(str, val));
    }
}

static void DumpStringClass([[maybe_unused]] JSThread *thread, const EcmaString *str,
                            std::vector<std::pair<PandaString, JSTaggedValue>> &vec)
{
    vec.emplace_back(std::make_pair("string", JSTaggedValue(str)));
}

static void DumpDynClass([[maybe_unused]] JSThread *thread, TaggedObject *obj,
                         std::vector<std::pair<PandaString, JSTaggedValue>> &vec)
{
    JSHClass *jshclass = obj->GetClass();
    vec.emplace_back(std::make_pair("__proto__", jshclass->GetPrototype()));
}

// NOLINTNEXTLINE(readability-function-size)
static void DumpObject(JSThread *thread, TaggedObject *obj, std::vector<std::pair<PandaString, JSTaggedValue>> &vec,
                       bool isVmMode)
{
    auto jsHclass = obj->GetClass();
    JSType type = jsHclass->GetObjectType();

    switch (type) {
        case JSType::HCLASS:
            DumpDynClass(thread, obj, vec);
            return;
        case JSType::TAGGED_ARRAY:
        case JSType::TAGGED_DICTIONARY:
            DumpArrayClass(thread, TaggedArray::Cast(obj), vec);
            return;
        case JSType::STRING:
            DumpStringClass(thread, EcmaString::Cast(obj), vec);
            return;
        case JSType::JS_NATIVE_POINTER:
            return;
        case JSType::JS_OBJECT:
        case JSType::JS_ERROR:
        case JSType::JS_EVAL_ERROR:
        case JSType::JS_RANGE_ERROR:
        case JSType::JS_TYPE_ERROR:
        case JSType::JS_REFERENCE_ERROR:
        case JSType::JS_URI_ERROR:
        case JSType::JS_SYNTAX_ERROR:
        case JSType::JS_ARGUMENTS:
        case JSType::JS_GLOBAL_OBJECT:
            JSObject::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_FUNCTION_BASE:
        case JSType::JS_FUNCTION:
            JSFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_BOUND_FUNCTION:
            JSBoundFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_SET:
            JSSet::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_MAP:
            JSMap::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_WEAK_SET:
            JSWeakSet::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_WEAK_MAP:
            JSWeakMap::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_REG_EXP:
            JSRegExp::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_DATE:
            JSDate::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_ARRAY:
            JSArray::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::BIGINT:
            BigInt::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_TYPED_ARRAY:
        case JSType::JS_INT8_ARRAY:
        case JSType::JS_UINT8_ARRAY:
        case JSType::JS_UINT8_CLAMPED_ARRAY:
        case JSType::JS_INT16_ARRAY:
        case JSType::JS_UINT16_ARRAY:
        case JSType::JS_INT32_ARRAY:
        case JSType::JS_UINT32_ARRAY:
        case JSType::JS_FLOAT32_ARRAY:
        case JSType::JS_FLOAT64_ARRAY:
            JSTypedArray::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_PROXY:
            JSProxy::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_PRIMITIVE_REF:
            JSPrimitiveRef::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::SYMBOL:
            JSSymbol::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::ACCESSOR_DATA:
        case JSType::INTERNAL_ACCESSOR:
            AccessorData::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_DATA_VIEW:
            JSDataView::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::PROMISE_REACTIONS:
            PromiseReaction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::PROMISE_CAPABILITY:
            PromiseCapability::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::PROMISE_ITERATOR_RECORD:
            PromiseIteratorRecord::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::PROMISE_RECORD:
            PromiseRecord::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::RESOLVING_FUNCTIONS_RECORD:
            ResolvingFunctionsRecord::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_PROMISE:
            JSPromise::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_PROMISE_REACTIONS_FUNCTION:
            JSPromiseReactionsFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_PROMISE_EXECUTOR_FUNCTION:
            JSPromiseExecutorFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION:
            JSPromiseAllResolveElementFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::MICRO_JOB_QUEUE:
            MicroJobQueue::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::PENDING_JOB:
            PendingJob::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::COMPLETION_RECORD:
            CompletionRecord::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_ITERATOR:
        case JSType::JS_FORIN_ITERATOR:
        case JSType::JS_MAP_ITERATOR:
        case JSType::JS_SET_ITERATOR:
        case JSType::JS_ARRAY_ITERATOR:
        case JSType::JS_STRING_ITERATOR:
        case JSType::JS_REG_EXP_ITERATOR:
        case JSType::JS_ARRAY_BUFFER:
            JSArrayBuffer::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_PROXY_REVOC_FUNCTION:
            JSProxyRevocFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_ASYNC_FUNCTION:
            JSAsyncFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION:
            JSAsyncAwaitStatusFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_ASYNC_GENERATOR_RESOLVE_NEXT_FUNCTION:
            JSAsyncGeneratorResolveNextFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_ASYNC_FROM_SYNC_ITERATOR_VALUE_UNWRAP_FUNCTION:
            JSAsyncFromSyncIteratorValueUnwrapFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_ASYNC_GENERATOR_FUNCTION:
            JSAsyncGeneratorFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_GENERATOR_FUNCTION:
            JSGeneratorFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_INTL_BOUND_FUNCTION:
            JSIntlBoundFunction::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_REALM:
            JSRealm::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_INTL:
            JSIntl::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_LOCALE:
            JSLocale::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_DATE_TIME_FORMAT:
            JSDateTimeFormat::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_RELATIVE_TIME_FORMAT:
            JSRelativeTimeFormat::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_NUMBER_FORMAT:
            JSNumberFormat::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_COLLATOR:
            JSCollator::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_PLURAL_RULES:
            JSPluralRules::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_GENERATOR_OBJECT:
            JSGeneratorObject::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_ASYNC_FUNC_OBJECT:
            JSAsyncFuncObject::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_GENERATOR_CONTEXT:
            GeneratorContext::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::FUNCTION_EXTRA_INFO:
            JSFunctionExtraInfo::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::ECMA_MODULE:
            EcmaModule::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        case JSType::JS_ARRAY_LIST:
            JSArrayList::Cast(obj)->DumpForSnapshot(thread, vec);
            return;
        default:
            break;
    }
    if (isVmMode) {
        switch (type) {
            case JSType::PROPERTY_BOX:
                PropertyBox::Cast(obj)->DumpForSnapshot(thread, vec);
                return;
            case JSType::TEMPLATE_MAP:
                DumpArrayClass(thread, TaggedArray::Cast(obj), vec);
                return;
            case JSType::LEXICAL_FUNCTION:
                LexicalFunction::Cast(obj)->DumpForSnapshot(thread, vec);
                return;
            case JSType::GLOBAL_ENV:
                GlobalEnv::Cast(obj)->DumpForSnapshot(thread, vec);
                return;
            case JSType::PROTO_CHANGE_MARKER:
                ProtoChangeMarker::Cast(obj)->DumpForSnapshot(thread, vec);
                return;
            case JSType::PROTOTYPE_INFO:
                ProtoChangeDetails::Cast(obj)->DumpForSnapshot(thread, vec);
                return;
            case JSType::PROGRAM:
                Program::Cast(obj)->DumpForSnapshot(thread, vec);
                return;
            case JSType::TRANSITION_HANDLER:
                TransitionHandler::Cast(obj)->DumpForSnapshot(thread, vec);
                return;
            case JSType::PROTOTYPE_HANDLER:
                PrototypeHandler::Cast(obj)->DumpForSnapshot(thread, vec);
                return;
            case JSType::CLASS_INFO_EXTRACTOR:
                ClassInfoExtractor::Cast(obj)->DumpForSnapshot(thread, vec);
                return;
            default:
                UNREACHABLE();
                break;
        }
    }
}

static inline void EcmaStringToStd(PandaString &res, EcmaString *str)
{
    if (str->GetLength() == 0) {
        PandaString emptyStr = "EmptyString";
        res.append(emptyStr);
    }

    PandaString string = ConvertToPandaString(str);
    res.append(string);
}

static void KeyToStd(PandaString &res, JSTaggedValue key)
{
    if (key.IsInt()) {
        res = std::to_string(key.GetInt());
    } else if (key.IsDouble()) {
        res = std::to_string(key.GetDouble());
    } else if (key.IsBoolean()) {
        res = key.IsTrue() ? "true" : "false";
    } else if (key.IsHeapObject()) {
        if (key.IsWeak()) {
            key.RemoveWeakTag();
        }
        if (key.IsString()) {
            EcmaStringToStd(res, EcmaString::Cast(key.GetTaggedObject()));
        } else if (key.IsSymbol()) {
            JSSymbol *sym = JSSymbol::Cast(key.GetTaggedObject());
            EcmaStringToStd(res, EcmaString::Cast(sym->GetDescription().GetTaggedObject()));
        }
    }
}

void JSTaggedValue::DumpForSnapshot(JSThread *thread, std::vector<std::pair<PandaString, JSTaggedValue>> &vec,
                                    bool isVmMode) const
{
    if (IsHeapObject()) {
        return DumpObject(thread, GetTaggedObject(), vec, isVmMode);
    }

    UNREACHABLE();
}

void NumberDictionary::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                       std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    int size = Size();
    for (int hashIndex = 0; hashIndex < size; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
            JSTaggedValue val(GetValue(hashIndex));
            PandaString str = ToPandaString(static_cast<uint32_t>(JSTaggedNumber(key).GetNumber()));
            vec.emplace_back(std::make_pair(str, val));
        }
    }
}

void NameDictionary::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                     std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    int size = Size();
    for (int hashIndex = 0; hashIndex < size; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
            JSTaggedValue val(GetValue(hashIndex));
            PandaString str;
            KeyToStd(str, key);
            vec.emplace_back(std::make_pair(str, val));
        }
    }
}

void GlobalDictionary::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                       std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    int size = Size();
    for (int hashIndex = 0; hashIndex < size; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
            PandaString str;
            KeyToStd(str, key);
            JSTaggedValue val = GetValue(hashIndex);
            vec.emplace_back(std::make_pair(str, val));
        }
    }
}

void LinkedHashSet::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                    std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    int capacity = NumberOfElements() + NumberOfDeletedElements();
    for (int hashIndex = 0; hashIndex < capacity; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
            PandaString str;
            KeyToStd(str, key);
            vec.emplace_back(std::make_pair(str, JSTaggedValue::Hole()));
        }
    }
}

void LinkedHashMap::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                    std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    int capacity = NumberOfElements() + NumberOfDeletedElements();
    for (int hashIndex = 0; hashIndex < capacity; hashIndex++) {
        JSTaggedValue key(GetKey(hashIndex));
        if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
            JSTaggedValue val = GetValue(hashIndex);
            PandaString str;
            KeyToStd(str, key);
            vec.emplace_back(std::make_pair(str, val));
        }
    }
}

void JSObject::DumpForSnapshot(JSThread *thread, std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    JSHClass *jshclass = GetJSHClass();
    vec.emplace_back(std::make_pair("__proto__", jshclass->GetPrototype()));

    TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
    if (elements->GetLength() == 0) {
    } else if (!elements->IsDictionaryMode()) {
        DumpArrayClass(thread, elements, vec);
    } else {
        NumberDictionary *dict = NumberDictionary::Cast(elements);
        dict->DumpForSnapshot(thread, vec);
    }

    TaggedArray *properties = TaggedArray::Cast(GetProperties().GetTaggedObject());
    if (IsJSGlobalObject()) {
        GlobalDictionary *dict = GlobalDictionary::Cast(properties);
        dict->DumpForSnapshot(thread, vec);
        return;
    }

    if (!properties->IsDictionaryMode()) {
        JSTaggedValue attrs = jshclass->GetLayout();
        if (attrs.IsNull()) {
            return;
        }

        LayoutInfo *layoutInfo = LayoutInfo::Cast(attrs.GetTaggedObject());
        int propNumber = jshclass->NumberOfProps();
        for (int i = 0; i < propNumber; i++) {
            JSTaggedValue key = layoutInfo->GetKey(i);
            PropertyAttributes attr = layoutInfo->GetAttr(i);
            ASSERT(i == static_cast<int>(attr.GetOffset()));
            JSTaggedValue val;
            if (attr.IsInlinedProps()) {
                val = GetPropertyInlinedProps(i);
            } else {
                val = properties->Get(i - jshclass->GetInlinedProperties());
            }

            PandaString str;
            KeyToStd(str, key);
            vec.emplace_back(std::make_pair(str, val));
        }
    } else {
        NameDictionary *dict = NameDictionary::Cast(properties);
        dict->DumpForSnapshot(thread, vec);
    }
}

void JSHClass::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                               [[maybe_unused]] std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
}

void JSFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                 std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("ProtoOrDynClass"), GetProtoOrDynClass()));
    vec.emplace_back(std::make_pair(PandaString("LexicalEnv"), GetLexicalEnv()));
    vec.emplace_back(std::make_pair(PandaString("HomeObject"), GetHomeObject()));
    vec.emplace_back(std::make_pair(PandaString("FunctionInfoFlag"), GetFunctionInfoFlag()));
    vec.emplace_back(std::make_pair(PandaString("FunctionExtraInfo"), GetFunctionExtraInfo()));
    vec.emplace_back(std::make_pair(PandaString("ConstantPool"), GetConstantPool()));
    vec.emplace_back(std::make_pair(PandaString("ProfileTypeInfo"), GetProfileTypeInfo()));
    JSObject::DumpForSnapshot(thread, vec);
}

void Program::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                              std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Location"), GetLocation()));
    vec.emplace_back(std::make_pair(PandaString("ConstantPool"), GetConstantPool()));
    vec.emplace_back(std::make_pair(PandaString("MainFunction"), GetMainFunction()));
    // MethodsData is another native field, and we don't dump it for JS heap.
    vec.emplace_back(std::make_pair(PandaString("NumberMethods"), JSTaggedValue(GetMethodsData()->size())));
}

void ConstantPool::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                   std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    DumpArrayClass(thread, this, vec);
}

void JSConstructorFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                            std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    JSObject::DumpForSnapshot(thread, vec);

    vec.emplace_back(std::make_pair(PandaString("ComputedFields"), GetComputedFields()));
    vec.emplace_back(std::make_pair(PandaString("PrivateFields"), GetPrivateFields()));
}

void JSBoundFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                      std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    JSObject::DumpForSnapshot(thread, vec);

    vec.emplace_back(std::make_pair(PandaString("BoundTarget"), GetBoundTarget()));
    vec.emplace_back(std::make_pair(PandaString("BoundThis"), GetBoundThis()));
    vec.emplace_back(std::make_pair(PandaString("BoundArguments"), GetBoundArguments()));
}

void JSPrimitiveRef::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                     std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("subValue"), GetValue()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSDate::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                             std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("time"), GetTime()));
    vec.emplace_back(std::make_pair(PandaString("localOffset"), GetLocalOffset()));

    JSObject::DumpForSnapshot(thread, vec);
}

void JSMap::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                            std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    LinkedHashMap *map = LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject());
    map->DumpForSnapshot(thread, vec);

    JSObject::DumpForSnapshot(thread, vec);
}

void JSForInIterator::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                      std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Object"), GetObject()));
    vec.emplace_back(std::make_pair(PandaString("WasVisited"), GetWasVisited()));
    vec.emplace_back(std::make_pair(PandaString("VisitedKeys"), GetVisitedKeys()));
    vec.emplace_back(std::make_pair(PandaString("RemainingKeys"), GetRemainingKeys()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSMapIterator::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                    std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    LinkedHashMap *map = LinkedHashMap::Cast(GetIteratedMap().GetTaggedObject());
    map->DumpForSnapshot(thread, vec);
    vec.emplace_back(std::make_pair(PandaString("NextIndex"), GetNextIndex()));
    vec.emplace_back(std::make_pair(PandaString("IterationKind"), GetIterationKind()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSSet::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                            std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    LinkedHashSet *set = LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject());
    set->DumpForSnapshot(thread, vec);

    JSObject::DumpForSnapshot(thread, vec);
}

void JSWeakMap::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    LinkedHashMap *map = LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject());
    map->DumpForSnapshot(thread, vec);

    JSObject::DumpForSnapshot(thread, vec);
}

void JSWeakSet::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    LinkedHashSet *set = LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject());
    set->DumpForSnapshot(thread, vec);

    JSObject::DumpForSnapshot(thread, vec);
}
void JSSetIterator::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                    std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    LinkedHashSet *set = LinkedHashSet::Cast(GetIteratedSet().GetTaggedObject());
    set->DumpForSnapshot(thread, vec);
    vec.emplace_back(std::make_pair(PandaString("NextIndex"), GetNextIndex()));
    vec.emplace_back(std::make_pair(PandaString("IterationKind"), GetIterationKind()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSArray::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                              std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    JSObject::DumpForSnapshot(thread, vec);
}

void BigInt::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                             std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Data"), GetData()));
    vec.emplace_back(std::make_pair(PandaString("Sign"), JSTaggedValue(GetSign())));
}

void JSArrayList::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                  std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    JSObject::DumpForSnapshot(thread, vec);
}

void JSArrayIterator::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                      std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    JSArray *array = JSArray::Cast(GetIteratedArray().GetTaggedObject());
    array->DumpForSnapshot(thread, vec);
    vec.emplace_back(std::make_pair(PandaString("NextIndex"), GetNextIndex()));
    vec.emplace_back(std::make_pair(PandaString("IterationKind"), GetIterationKind()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSStringIterator::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                       std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("IteratedString"), GetIteratedString()));
    vec.emplace_back(std::make_pair(PandaString("StringIteratorNextIndex"), GetStringIteratorNextIndex()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSTypedArray::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                   std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("viewed-array-buffer"), GetViewedArrayBuffer()));
    vec.emplace_back(std::make_pair(PandaString("typed-array-name"), GetTypedArrayName()));
    vec.emplace_back(std::make_pair(PandaString("byte-length"), GetByteLength()));
    vec.emplace_back(std::make_pair(PandaString("byte-offset"), GetByteOffset()));
    vec.emplace_back(std::make_pair(PandaString("array-length"), GetArrayLength()));
}

void JSRegExp::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                               std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("originalSource"), GetOriginalSource()));
    vec.emplace_back(std::make_pair(PandaString("originalFlags"), GetOriginalFlags()));

    JSObject::DumpForSnapshot(thread, vec);
}

void JSProxy::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                              std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("target"), GetTarget()));
    vec.emplace_back(std::make_pair(PandaString("handler"), GetHandler()));
}

void JSSymbol::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                               std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("hash-field"), GetHashField()));
    vec.emplace_back(std::make_pair(PandaString("flags"), GetFlags()));
    vec.emplace_back(std::make_pair(PandaString("description"), GetDescription()));
}

void AccessorData::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                   std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("getter"), GetGetter()));
    vec.emplace_back(std::make_pair(PandaString("setter"), GetSetter()));
}

void LexicalEnv::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                 std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    DumpArrayClass(thread, this, vec);
}

void GlobalEnv::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    auto globalConst = thread->GlobalConstants();
    vec.emplace_back(std::make_pair(PandaString("ObjectFunction"), GetObjectFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("FunctionFunction"), GetFunctionFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("NumberFunction"), GetNumberFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("BigIntFunction"), GetBigIntFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("DateFunction"), GetDateFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("BooleanFunction"), GetBooleanFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ErrorFunction"), GetErrorFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ArrayFunction"), GetArrayFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("TypedArrayFunction"), GetTypedArrayFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("Int8ArrayFunction"), GetInt8ArrayFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("Uint8ArrayFunction"), GetUint8ArrayFunction().GetTaggedValue()));
    vec.emplace_back(
        std::make_pair(PandaString("Uint8ClampedArrayFunction"), GetUint8ClampedArrayFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("Int16ArrayFunction"), GetInt16ArrayFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("Uint16ArrayFunction"), GetUint16ArrayFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("Int32ArrayFunction"), GetInt32ArrayFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("Uint32ArrayFunction"), GetUint32ArrayFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("Float32ArrayFunction"), GetFloat32ArrayFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("Float64ArrayFunction"), GetFloat64ArrayFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ArrayBufferFunction"), GetArrayBufferFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("SymbolFunction"), GetSymbolFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("RangeErrorFunction"), GetRangeErrorFunction().GetTaggedValue()));
    vec.emplace_back(
        std::make_pair(PandaString("ReferenceErrorFunction"), GetReferenceErrorFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("TypeErrorFunction"), GetTypeErrorFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("URIErrorFunction"), GetURIErrorFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("SyntaxErrorFunction"), GetSyntaxErrorFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("EvalErrorFunction"), GetEvalErrorFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("RegExpFunction"), GetRegExpFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("SetFunction"), GetSetFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("MapFunction"), GetMapFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("BuiltinsWeakSetFunction"), GetWeakSetFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("BuiltinsWeakMapFunction"), GetWeakMapFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("MathFunction"), GetMathFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("JsonFunction"), GetJsonFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("StringFunction"), GetStringFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ProxyFunction"), GetProxyFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ReflectFunction"), GetReflectFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("AsyncFunction"), GetAsyncFunction().GetTaggedValue()));
    vec.emplace_back(
        std::make_pair(PandaString("AsyncFunctionPrototype"), GetAsyncFunctionPrototype().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("JSGlobalObject"), GetJSGlobalObject().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("EmptyArray"), GetEmptyArray().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("EmptyString"), globalConst->GetEmptyString()));
    vec.emplace_back(std::make_pair(PandaString("EmptyTaggedQueue"), GetEmptyTaggedQueue().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("PrototypeString"), globalConst->GetPrototypeString()));
    vec.emplace_back(std::make_pair(PandaString("HasInstanceSymbol"), GetHasInstanceSymbol().GetTaggedValue()));
    vec.emplace_back(
        std::make_pair(PandaString("IsConcatSpreadableSymbol"), GetIsConcatSpreadableSymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ToStringTagSymbol"), GetToStringTagSymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("IteratorSymbol"), GetIteratorSymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("MatchSymbol"), GetMatchSymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ReplaceSymbol"), GetReplaceSymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("SearchSymbol"), GetSearchSymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("SpeciesSymbol"), GetSpeciesSymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("SplitSymbol"), GetSplitSymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ToPrimitiveSymbol"), GetToPrimitiveSymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("UnscopablesSymbol"), GetUnscopablesSymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("HoleySymbol"), GetHoleySymbol().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ConstructorString"), globalConst->GetConstructorString()));
    vec.emplace_back(std::make_pair(PandaString("IteratorPrototype"), GetIteratorPrototype().GetTaggedValue()));
    vec.emplace_back(
        std::make_pair(PandaString("ForinIteratorPrototype"), GetForinIteratorPrototype().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("StringIterator"), GetStringIteratorFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("MapIteratorPrototype"), GetMapIteratorPrototype().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("SetIteratorPrototype"), GetSetIteratorPrototype().GetTaggedValue()));
    vec.emplace_back(
        std::make_pair(PandaString("RegExpIteratorPrototype"), GetRegExpIteratorPrototype().GetTaggedValue()));
    vec.emplace_back(
        std::make_pair(PandaString("ArrayIteratorPrototype"), GetArrayIteratorPrototype().GetTaggedValue()));
    vec.emplace_back(
        std::make_pair(PandaString("StringIteratorPrototype"), GetStringIteratorPrototype().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("LengthString"), globalConst->GetLengthString()));
    vec.emplace_back(std::make_pair(PandaString("ValueString"), globalConst->GetValueString()));
    vec.emplace_back(std::make_pair(PandaString("WritableString"), globalConst->GetWritableString()));
    vec.emplace_back(std::make_pair(PandaString("GetString"), globalConst->GetGetString()));
    vec.emplace_back(std::make_pair(PandaString("SetString"), globalConst->GetSetString()));
    vec.emplace_back(std::make_pair(PandaString("EnumerableString"), globalConst->GetEnumerableString()));
    vec.emplace_back(std::make_pair(PandaString("ConfigurableString"), globalConst->GetConfigurableString()));
    vec.emplace_back(std::make_pair(PandaString("NameString"), globalConst->GetNameString()));
    vec.emplace_back(std::make_pair(PandaString("ValueOfString"), globalConst->GetValueOfString()));
    vec.emplace_back(std::make_pair(PandaString("ToStringString"), globalConst->GetToStringString()));
    vec.emplace_back(std::make_pair(PandaString("ToLocaleStringString"), globalConst->GetToLocaleStringString()));
    vec.emplace_back(std::make_pair(PandaString("UndefinedString"), globalConst->GetUndefinedString()));
    vec.emplace_back(std::make_pair(PandaString("NullString"), globalConst->GetNullString()));
    vec.emplace_back(std::make_pair(PandaString("TrueString"), globalConst->GetTrueString()));
    vec.emplace_back(std::make_pair(PandaString("FalseString"), globalConst->GetFalseString()));
    vec.emplace_back(std::make_pair(PandaString("RegisterSymbols"), GetRegisterSymbols().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ThrowTypeError"), GetThrowTypeError().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("GetPrototypeOfString"), globalConst->GetGetPrototypeOfString()));
    vec.emplace_back(std::make_pair(PandaString("SetPrototypeOfString"), globalConst->GetSetPrototypeOfString()));
    vec.emplace_back(std::make_pair(PandaString("IsExtensibleString"), globalConst->GetIsExtensibleString()));
    vec.emplace_back(std::make_pair(PandaString("PreventExtensionsString"), globalConst->GetPreventExtensionsString()));
    vec.emplace_back(std::make_pair(PandaString("GetOwnPropertyDescriptorString"),
                                    globalConst->GetGetOwnPropertyDescriptorString()));
    vec.emplace_back(std::make_pair(PandaString("DefinePropertyString"), globalConst->GetDefinePropertyString()));
    vec.emplace_back(std::make_pair(PandaString("HasString"), globalConst->GetHasString()));
    vec.emplace_back(std::make_pair(PandaString("DeletePropertyString"), globalConst->GetDeletePropertyString()));
    vec.emplace_back(std::make_pair(PandaString("EnumerateString"), globalConst->GetEnumerateString()));
    vec.emplace_back(std::make_pair(PandaString("OwnKeysString"), globalConst->GetOwnKeysString()));
    vec.emplace_back(std::make_pair(PandaString("ApplyString"), globalConst->GetApplyString()));
    vec.emplace_back(std::make_pair(PandaString("ProxyString"), globalConst->GetProxyString()));
    vec.emplace_back(std::make_pair(PandaString("RevokeString"), globalConst->GetRevokeString()));
    vec.emplace_back(std::make_pair(PandaString("ProxyConstructString"), globalConst->GetProxyConstructString()));
    vec.emplace_back(std::make_pair(PandaString("ProxyCallString"), globalConst->GetProxyCallString()));
    vec.emplace_back(std::make_pair(PandaString("DoneString"), globalConst->GetDoneString()));
    vec.emplace_back(std::make_pair(PandaString("NegativeZeroString"), globalConst->GetNegativeZeroString()));
    vec.emplace_back(std::make_pair(PandaString("NextString"), globalConst->GetNextString()));
    vec.emplace_back(std::make_pair(PandaString("PromiseThenString"), globalConst->GetPromiseThenString()));
    vec.emplace_back(std::make_pair(PandaString("PromiseFunction"), GetPromiseFunction().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("PromiseReactionJob"), GetPromiseReactionJob().GetTaggedValue()));
    vec.emplace_back(
        std::make_pair(PandaString("PromiseResolveThenableJob"), GetPromiseResolveThenableJob().GetTaggedValue()));
    vec.emplace_back(std::make_pair(PandaString("ScriptJobString"), globalConst->GetScriptJobString()));
    vec.emplace_back(std::make_pair(PandaString("PromiseString"), globalConst->GetPromiseString()));
    vec.emplace_back(std::make_pair(PandaString("IdentityString"), globalConst->GetIdentityString()));
    vec.emplace_back(std::make_pair(PandaString("AsyncFunctionString"), globalConst->GetAsyncFunctionString()));
    vec.emplace_back(std::make_pair(PandaString("ThrowerString"), globalConst->GetThrowerString()));
    vec.emplace_back(std::make_pair(PandaString("Undefined"), globalConst->GetUndefined()));
}

void JSDataView::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                 std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("data-view"), GetDataView()));
    vec.emplace_back(std::make_pair(PandaString("buffer"), GetViewedArrayBuffer()));
    vec.emplace_back(std::make_pair(PandaString("byte-length"), GetByteLength()));
    vec.emplace_back(std::make_pair(PandaString("byte-offset"), GetByteOffset()));
}

void JSArrayBuffer::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                    std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("byte-length"), GetArrayBufferByteLength()));
    vec.emplace_back(std::make_pair(PandaString("buffer-data"), GetArrayBufferData()));
    vec.emplace_back(std::make_pair(PandaString("shared"), GetShared()));
}

void PromiseReaction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                      std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("promise-capability"), GetPromiseCapability()));
    vec.emplace_back(std::make_pair(PandaString("type"), GetType()));
    vec.emplace_back(std::make_pair(PandaString("handler"), GetHandler()));
}

void PromiseCapability::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                        std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("promise"), GetPromise()));
    vec.emplace_back(std::make_pair(PandaString("resolve"), GetResolve()));
    vec.emplace_back(std::make_pair(PandaString("reject"), GetReject()));
}

void PromiseIteratorRecord::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                            std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("iterator"), GetIterator()));
    vec.emplace_back(std::make_pair(PandaString("done"), GetDone()));
}

void PromiseRecord::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                    std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("value"), GetValue()));
}

void ResolvingFunctionsRecord::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                               std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("resolve-function"), GetResolveFunction()));
    vec.emplace_back(std::make_pair(PandaString("reject-function"), GetRejectFunction()));
}

void JSPromise::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("promise-state"), GetPromiseState()));
    vec.emplace_back(std::make_pair(PandaString("promise-result"), GetPromiseResult()));
    vec.emplace_back(std::make_pair(PandaString("promise-fulfill-reactions"), GetPromiseFulfillReactions()));
    vec.emplace_back(std::make_pair(PandaString("promise-reject-reactions"), GetPromiseRejectReactions()));
    vec.emplace_back(std::make_pair(PandaString("promise-is-handled"), GetPromiseIsHandled()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSPromiseReactionsFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                                 std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("promise"), GetPromise()));
    vec.emplace_back(std::make_pair(PandaString("already-resolved"), GetAlreadyResolved()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSPromiseExecutorFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                                std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("capability"), GetCapability()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSPromiseAllResolveElementFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                                         std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("index"), GetIndex()));
    vec.emplace_back(std::make_pair(PandaString("values"), GetValues()));
    vec.emplace_back(std::make_pair(PandaString("capabilities"), GetCapabilities()));
    vec.emplace_back(std::make_pair(PandaString("remaining-elements"), GetRemainingElements()));
    vec.emplace_back(std::make_pair(PandaString("already-called"), GetAlreadyCalled()));
    JSObject::DumpForSnapshot(thread, vec);
}

void MicroJobQueue::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                    std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("promise-job-queue"), GetPromiseJobQueue()));
    vec.emplace_back(std::make_pair(PandaString("script-job-queue"), GetScriptJobQueue()));
}

void PendingJob::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                 std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("job"), GetJob()));
    vec.emplace_back(std::make_pair(PandaString("arguments"), GetArguments()));
}

void CompletionRecord::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                       std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("type"), GetType()));
    vec.emplace_back(std::make_pair(PandaString("value"), GetValue()));
}

void JSProxyRevocFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                           std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("RevocableProxy"), GetRevocableProxy()));
}

void JSAsyncFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                      std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    JSFunction::DumpForSnapshot(thread, vec);
}

void JSAsyncGeneratorResolveNextFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                                          std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("AsyncGenerator"), GetAsyncGenerator()));
}

void JSAsyncFromSyncIteratorValueUnwrapFunction::DumpForSnapshot(
    [[maybe_unused]] JSThread *thread, std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("done"), GetDone()));
}

void JSAsyncAwaitStatusFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                                 std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("AsyncContext"), GetAsyncContext()));
}

void JSGeneratorFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                          std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    JSFunction::DumpForSnapshot(thread, vec);
}

void JSIntlBoundFunction::DumpForSnapshot(JSThread *thread,
                                          std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("NumberFormat"), GetNumberFormat()));
    vec.emplace_back(std::make_pair(PandaString("DateTimeFormat"), GetDateTimeFormat()));
    vec.emplace_back(std::make_pair(PandaString("Collator"), GetCollator()));
    JSObject::DumpForSnapshot(thread, vec);
}

void PropertyBox::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                  std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Value"), GetValue()));
}

void PrototypeHandler::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                       std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("HandlerInfo"), GetHandlerInfo()));
    vec.emplace_back(std::make_pair(PandaString("ProtoCell"), GetProtoCell()));
    vec.emplace_back(std::make_pair(PandaString("Holder"), GetHolder()));
}

void TransitionHandler::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                        std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("HandlerInfo"), GetHandlerInfo()));
    vec.emplace_back(std::make_pair(PandaString("TransitionHClass"), GetTransitionHClass()));
}

void JSRealm::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                              std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Value"), GetValue()));
    vec.emplace_back(std::make_pair(PandaString("GLobalEnv"), GetGlobalEnv()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSIntl::DumpForSnapshot(JSThread *thread, std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("FallbackSymbol"), GetFallbackSymbol()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSLocale::DumpForSnapshot(JSThread *thread, std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("IcuField"), GetIcuField()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSDateTimeFormat::DumpForSnapshot(JSThread *thread, std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Locale"), GetLocale()));
    vec.emplace_back(std::make_pair(PandaString("Calendar"), GetCalendar()));
    vec.emplace_back(std::make_pair(PandaString("NumberingSystem"), GetNumberingSystem()));
    vec.emplace_back(std::make_pair(PandaString("TimeZone"), GetTimeZone()));
    vec.emplace_back(std::make_pair(PandaString("HourCycle"), GetHourCycle()));
    vec.emplace_back(std::make_pair(PandaString("LocaleIcu"), GetLocaleIcu()));
    vec.emplace_back(std::make_pair(PandaString("SimpleDateTimeFormatIcu"), GetSimpleDateTimeFormatIcu()));
    vec.emplace_back(std::make_pair(PandaString("Iso8601"), GetIso8601()));
    vec.emplace_back(std::make_pair(PandaString("DateStyle"), GetDateStyle()));
    vec.emplace_back(std::make_pair(PandaString("TimeStyle"), GetTimeStyle()));
    vec.emplace_back(std::make_pair(PandaString("BoundFormat"), GetBoundFormat()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSRelativeTimeFormat::DumpForSnapshot(JSThread *thread,
                                           std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Locale"), GetLocale()));
    vec.emplace_back(std::make_pair(PandaString("InitializedRelativeTimeFormat"), GetInitializedRelativeTimeFormat()));
    vec.emplace_back(std::make_pair(PandaString("NumberingSystem"), GetNumberingSystem()));
    vec.emplace_back(std::make_pair(PandaString("Style"), GetStyle()));
    vec.emplace_back(std::make_pair(PandaString("Numeric"), GetNumeric()));
    vec.emplace_back(std::make_pair(PandaString("AvailableLocales"), GetAvailableLocales()));
    vec.emplace_back(std::make_pair(PandaString("IcuField"), GetIcuField()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSNumberFormat::DumpForSnapshot(JSThread *thread, std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Locale"), GetLocale()));
    vec.emplace_back(std::make_pair(PandaString("NumberingSystem"), GetNumberingSystem()));
    vec.emplace_back(std::make_pair(PandaString("Style"), GetStyle()));
    vec.emplace_back(std::make_pair(PandaString("Currency"), GetCurrency()));
    vec.emplace_back(std::make_pair(PandaString("CurrencyDisplay"), GetCurrencyDisplay()));
    vec.emplace_back(std::make_pair(PandaString("CurrencySign"), GetCurrencySign()));
    vec.emplace_back(std::make_pair(PandaString("Unit"), GetUnit()));
    vec.emplace_back(std::make_pair(PandaString("UnitDisplay"), GetUnitDisplay()));
    vec.emplace_back(std::make_pair(PandaString("MinimumIntegerDigits"), GetMinimumIntegerDigits()));
    vec.emplace_back(std::make_pair(PandaString("MinimumFractionDigits"), GetMinimumFractionDigits()));
    vec.emplace_back(std::make_pair(PandaString("MaximumFractionDigits"), GetMaximumFractionDigits()));
    vec.emplace_back(std::make_pair(PandaString("MinimumSignificantDigits"), GetMinimumSignificantDigits()));
    vec.emplace_back(std::make_pair(PandaString("MaximumSignificantDigits"), GetMaximumSignificantDigits()));
    vec.emplace_back(std::make_pair(PandaString("UseGrouping"), GetUseGrouping()));
    vec.emplace_back(std::make_pair(PandaString("RoundingType"), GetRoundingType()));
    vec.emplace_back(std::make_pair(PandaString("Notation"), GetNotation()));
    vec.emplace_back(std::make_pair(PandaString("CompactDisplay"), GetCompactDisplay()));
    vec.emplace_back(std::make_pair(PandaString("SignDisplay"), GetSignDisplay()));
    vec.emplace_back(std::make_pair(PandaString("BoundFormat"), GetBoundFormat()));
    vec.emplace_back(std::make_pair(PandaString("IcuField"), GetIcuField()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSCollator::DumpForSnapshot(JSThread *thread, std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("IcuField"), GetIcuField()));
    vec.emplace_back(std::make_pair(PandaString("Locale"), GetLocale()));
    vec.emplace_back(std::make_pair(PandaString("Usage"), GetUsage()));
    vec.emplace_back(std::make_pair(PandaString("Sensitivity"), GetSensitivity()));
    vec.emplace_back(std::make_pair(PandaString("IgnorePunctuation"), GetIgnorePunctuation()));
    vec.emplace_back(std::make_pair(PandaString("Collation"), GetCollation()));
    vec.emplace_back(std::make_pair(PandaString("Numeric"), GetNumeric()));
    vec.emplace_back(std::make_pair(PandaString("CaseFirst"), GetCaseFirst()));
    vec.emplace_back(std::make_pair(PandaString("BoundCompare"), GetBoundCompare()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSPluralRules::DumpForSnapshot(JSThread *thread, std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Locale"), GetLocale()));
    vec.emplace_back(std::make_pair(PandaString("InitializedPluralRules"), GetInitializedPluralRules()));
    vec.emplace_back(std::make_pair(PandaString("Type"), GetType()));
    vec.emplace_back(std::make_pair(PandaString("MinimumIntegerDigits"), GetMinimumIntegerDigits()));
    vec.emplace_back(std::make_pair(PandaString("MinimumFractionDigits"), GetMinimumFractionDigits()));
    vec.emplace_back(std::make_pair(PandaString("MaximumFractionDigits"), GetMaximumFractionDigits()));
    vec.emplace_back(std::make_pair(PandaString("MinimumSignificantDigits"), GetMinimumSignificantDigits()));
    vec.emplace_back(std::make_pair(PandaString("MaximumSignificantDigits"), GetMaximumSignificantDigits()));
    vec.emplace_back(std::make_pair(PandaString("RoundingType"), GetRoundingType()));
    vec.emplace_back(std::make_pair(PandaString("IcuPR"), GetIcuPR()));
    vec.emplace_back(std::make_pair(PandaString("IcuNF"), GetIcuNF()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSGeneratorObject::DumpForSnapshot(JSThread *thread, std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("GeneratorState"), GetGeneratorState()));
    vec.emplace_back(std::make_pair(PandaString("GeneratorContext"), GetGeneratorContext()));
    vec.emplace_back(std::make_pair(PandaString("ResumeResult"), GetResumeResult()));
    vec.emplace_back(std::make_pair(PandaString("ResumeMode"), GetResumeMode()));
    JSObject::DumpForSnapshot(thread, vec);
}

void JSAsyncGeneratorFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                               std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    JSFunction::DumpForSnapshot(thread, vec);
}

void JSAsyncFuncObject::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                        std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Promise"), GetPromise()));
}

void GeneratorContext::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                       std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("RegsArray"), GetRegsArray()));
    vec.emplace_back(std::make_pair(PandaString("Method"), GetMethod()));
    vec.emplace_back(std::make_pair(PandaString("Acc"), GetAcc()));
    vec.emplace_back(std::make_pair(PandaString("NRegs"), GetNRegs()));
    vec.emplace_back(std::make_pair(PandaString("BCOffset"), GetBCOffset()));
    vec.emplace_back(std::make_pair(PandaString("GeneratorObject"), GetGeneratorObject()));
    vec.emplace_back(std::make_pair(PandaString("LexicalEnv"), GetLexicalEnv()));
}

void ProtoChangeMarker::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                        std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Promise"), JSTaggedValue(GetHasChanged())));
}

void ProtoChangeDetails::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                         std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("ChangeListener"), GetChangeListener()));
    vec.emplace_back(std::make_pair(PandaString("RegisterIndex"), GetRegisterIndex()));
}

void LexicalFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                      std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Name"), GetName()));
    vec.emplace_back(std::make_pair(PandaString("NumberVRegs"), GetNumberVRegs()));
    vec.emplace_back(std::make_pair(PandaString("NumberICSlots"), GetNumberICSlots()));
    vec.emplace_back(std::make_pair(PandaString("Bytecode"), GetBytecode()));
    vec.emplace_back(std::make_pair(PandaString("Program"), GetProgram()));
}

void JSFunctionExtraInfo::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                          std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("Callback"), GetCallback()));
    vec.emplace_back(std::make_pair(PandaString("Data"), GetData()));
}

void EcmaModule::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                 std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("NameDictionary"), GetNameDictionary()));
}

void ClassInfoExtractor::DumpForSnapshot([[maybe_unused]] JSThread *thread,
                                         std::vector<std::pair<PandaString, JSTaggedValue>> &vec) const
{
    vec.emplace_back(std::make_pair(PandaString("PrototypeHClass"), GetPrototypeHClass()));
    vec.emplace_back(std::make_pair(PandaString("NonStaticKeys"), GetNonStaticKeys()));
    vec.emplace_back(std::make_pair(PandaString("NonStaticProperties"), GetNonStaticProperties()));
    vec.emplace_back(std::make_pair(PandaString("NonStaticElements"), GetNonStaticElements()));
    vec.emplace_back(std::make_pair(PandaString("ConstructorHClass"), GetConstructorHClass()));
    vec.emplace_back(std::make_pair(PandaString("StaticKeys"), GetStaticKeys()));
    vec.emplace_back(std::make_pair(PandaString("StaticProperties"), GetStaticProperties()));
    vec.emplace_back(std::make_pair(PandaString("StaticElements"), GetStaticElements()));
}
}  // namespace ark::ecmascript
